Pointer to pointer with lots of examples

S

sheroork

Can anyone help me in getting to understand pointer to pointer with
examples?

Appritiate in advance.

Sagar
 
R

Richard Heathfield

sheroork said:
Can anyone help me in getting to understand pointer to pointer with
examples?

Phone up the Directory Enquiries service (192 if you're in the UK). Tell
them the name of the person you're looking for, and they'll tell you the
relevant phone number. You can then use that phone number to contact the
person you really want to talk to.

Translation: a pointer tells you where something is. But it, itself, has an
address, which you might need to find out before you can use it. So a
pointer to pointer simply tells you where a particular pointer is. A
pointer is like a phone number. Dereferencing the pointer is like making
the call. When the guy on the other end gives you another phone number,
you've just used a pointer (*his* number) to a pointer (the number he gives
you), and presumably you'll use that new pointer to find the information
(make the call) you really wanted to find (make).

Examples are tricky, in that any realistic working example is likely to be
way too big and complicated to make it a useful example. If you're not
afraid of big examples, though, let me know and I'll see what I can dig up
from my code base.
 
A

August Karlstrom

sheroork said:
Can anyone help me in getting to understand pointer to pointer with
examples?

int **p;

p
+---+
| ? |
+---+

p = malloc(sizeof *p);

p *p
+---+ +---+
| ----->| ? |
+---+ +---+

*p = malloc(sizeof **p);

p *p **p
+---+ +---+ +---+
| ----->| ----->| ? |
+---+ +---+ +---+

**p = 7;

p *p **p
+---+ +---+ +---+
| ----->| ----->| 7 |
+---+ +---+ +---+


August
 
B

Ben Pfaff

Richard Heathfield said:
sheroork said:


Examples are tricky, in that any realistic working example is likely to be
way too big and complicated to make it a useful example. If you're not
afraid of big examples, though, let me know and I'll see what I can dig up
from my code base.

Using a pointer to pointer to return a pointer value from a
function may be a simple way to come up with a short example.
 
R

Richard Heathfield

Ben Pfaff said:
Using a pointer to pointer to return a pointer value from a
function may be a simple way to come up with a short example.

Be my guest. :)

The problem with such examples, however, is that they tend to leave the
reader scratching his head and thinking "okay, I'm seeing some syntax, and
I think I understand that - but why would anyone do it like /that/ when
they could just, say, return the pointer value using 'return p;'?" You know
and I know that such code as foo(&ptr) is actually quite common, and for
good reason - but it's one thing to know and another to explain.

Maybe August had the right idea - a dynamic array of dynamic arrays.

T **p = malloc(rows * sizeof *p);
if(p != NULL)
{
size_t r = 0;
for(r = 0; r < rows; r++)
{
p[r] = malloc(cols * sizeof *p[r]);
if(p[r] == NULL) { handle_the_error(); }
}

Assuming all that worked okay, you now have a dynamically sized array, rows
* cols elements in size. Whilst there are other ways to achieve this, I
think pointer to pointer is actually the simplest solution for this
problem, so it makes a good example. Nice one, August.
 
B

Ben Pfaff

Richard Heathfield said:
Maybe August had the right idea - a dynamic array of dynamic arrays.

There is in an example of a multidimensional array using a
pointer-to-pointer in the FAQ. I thought about posting it
earlier but wasn't sure that it was simple enough.

6.16: How can I dynamically allocate a multidimensional array?

A: The traditional solution is to allocate an array of pointers,
and then initialize each pointer to a dynamically-allocated
"row." Here is a two-dimensional example:

#include <stdlib.h>

int **array1 = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
array1 = malloc(ncolumns * sizeof(int));

(In real code, of course, all of malloc's return values would
be checked.)

You can keep the array's contents contiguous, at the cost of
making later reallocation of individual rows more difficult,
with a bit of explicit pointer arithmetic:

int **array2 = malloc(nrows * sizeof(int *));
array2[0] = malloc(nrows * ncolumns * sizeof(int));
for(i = 1; i < nrows; i++)
array2 = array2[0] + i * ncolumns;

In either case, the elements of the dynamic array can be
accessed with normal-looking array subscripts: arrayx[j]
(for 0 <= i < nrows and 0 <= j < ncolumns).

If the double indirection implied by the above schemes is for
some reason unacceptable, you can simulate a two-dimensional
array with a single, dynamically-allocated one-dimensional
array:

int *array3 = malloc(nrows * ncolumns * sizeof(int));

However, you must now perform subscript calculations manually,
accessing the i,jth element with array3[i * ncolumns + j]. (A
macro could hide the explicit calculation, but invoking it would
require parentheses and commas which wouldn't look exactly like
multidimensional array syntax, and the macro would need access
to at least one of the dimensions, as well. See also question
6.19.)

Yet another option is to use pointers to arrays:

int (*array4)[NCOLUMNS] = malloc(nrows * sizeof(*array4));

but the syntax starts getting horrific and at most one dimension
may be specified at run time.

With all of these techniques, you may of course need to remember
to free the arrays (which may take several steps; see question
7.23) when they are no longer needed, and you cannot necessarily
intermix dynamically-allocated arrays with conventional,
statically-allocated ones (see question 6.20, and also question
6.18).

Finally, in C9X you can use a variable-length array.

All of these techniques can also be extended to three or more
dimensions.

References: C9X Sec. 6.5.5.2.
 
S

Scorpio

August said:
int **p;

p
+---+
| ? |
+---+

p = malloc(sizeof *p);

p *p
+---+ +---+
| ----->| ? |
+---+ +---+

*p = malloc(sizeof **p);

ITYM: *p=malloc(sizeof int);

p *p **p
+---+ +---+ +---+
| ----->| ----->| ? |
+---+ +---+ +---+

**p = 7;

p *p **p
+---+ +---+ +---+
| ----->| ----->| 7 |
+---+ +---+ +---+


August

Sharath A.V

-In the journey of life, failure is a lesson and success is an illusion.
 
R

Richard Heathfield

Scorpio said:
August Karlstrom wrote:

ITYM: *p=malloc(sizeof int);

No, HDNMT. For one thing, August's code is conceptually correct no matter
what the object type to which p points. And secondly, his code - unlike
yours - will actually compile.
 
S

Scorpio

Richard said:
Scorpio said:

No, HDNMT. For one thing, August's code is conceptually correct no matter
what the object type to which p points. And secondly, his code - unlike
yours - will actually compile.

Sorry, I was mistaken and yes, August's code is correct.
But I actually meant: *p=malloc(sizeof(int));
Is something wrong with this?

Even the code quoted by Ben from the FAQ is as follows:
int **array1 = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
array1 = malloc(ncolumns * sizeof(int));

BTW, what does HDNMT mean? I did try to find out, but found no results.

Sharath A.V
 
R

Richard Heathfield

Scorpio said:
Sorry, I was mistaken and yes, August's code is correct.
But I actually meant: *p=malloc(sizeof(int));
Is something wrong with this?

It will at least compile, but it's inferior to August's version, because
you're nailing the type to the call, possibly causing a maintenance
headache further down the line.
Even the code quoted by Ben from the FAQ is as follows:
int **array1 = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
array1 = malloc(ncolumns * sizeof(int));


Yeah, the FAQ is good but nobody ever claimed it was perfect.
BTW, what does HDNMT mean? I did try to find out, but found no results.

He Did Not Mean That. (i.e. he did not mean what you thought he meant.)
 
F

Flash Gordon

Morris said:
sheroork (in (e-mail address removed))
said:

| Can anyone help me in getting to understand pointer to pointer with
| examples?

Sagar...

The explanations posted so far look good. These two links make up
another example of how pointers to pointers might be used:

http://www.iedu.com/mrd/c/tokenize.c
http://www.iedu.com/mrd/c/tokfile.c

They look more like an example of how not to write C to me.

Rather than having a tokenize.h containing the prototype for the
tokenize function it has the prototype repeated in tokfile.c. So you
have to maintain it in two places with no help from the compiler.

Using a file scope variable for the function to determine if a character
is a word separator or part of a word instead of passing it down. What
is worse, a single character name for it!

Assuming ASCII or similar character encoding instead of using the
portable standard is* functions.

Increasing the hard to follow coupling by using another file scope
variable s to hold a pointer to the character being processed. The
author seems to have a major objection to using parameters!

Using recursion for what could more simply be implemented with a for
loop, and the state being passed down via the afore mentioned file scope
variables instead of parameters!

That code is so needlessly convoluted that pointing a beginner at it is
tantamount to cruelty!
 
S

sheroork

Thanks friends for all your time and knowledge you have posted.
I will be greatful for your postings.

Thanks,
Sagar
 
T

Tom St Denis

August said:
int **p;

p
+---+
| ? |
+---+

p = malloc(sizeof *p);

p *p
+---+ +---+
| ----->| ? |
+---+ +---+

*p = malloc(sizeof **p);

p *p **p
+---+ +---+ +---+
| ----->| ----->| ? |
+---+ +---+ +---+

**p = 7;

p *p **p
+---+ +---+ +---+
| ----->| ----->| 7 |
+---+ +---+ +---+

I, for one, welcome our ASCII art overlords.

Tom
 
D

Default User

Richard said:
Scorpio said:

It will at least compile, but it's inferior to August's version,
because you're nailing the type to the call, possibly causing a
maintenance headache further down the line.


After all, we just got done diagnosing an incorrect malloc call in
another thread. The deference the target method isn't fool-proof, of
course, but it's closer. You still have the cut and paste problem, but
it's a tad more recognizable because you have the two variable names on
the same line, whereas the types are often widely separated.



Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top