More on pointers to pointers.

C

Chad

I suspect I'm missing a broader concept here. Okay, given the following
code:

#include <stdio.h>

int main(void) {
char *ptr[] = {"Garbage", "test", "work"};
char **arg;

arg = ptr;

printf("The string is: %s\n", ptr[1]);
return 0;
}

Why am I not allowed to do something like:
arg = &ptr; ?

I guess even more to the point, why is this legal?
arg = &(*ptr) ;

Chad
 
R

Richard Heathfield

Chad said:
I suspect I'm missing a broader concept here. Okay, given the following
code:

#include <stdio.h>

int main(void) {
char *ptr[] = {"Garbage", "test", "work"};
char **arg;

arg = ptr;

printf("The string is: %s\n", ptr[1]);
return 0;
}

Why am I not allowed to do something like:
arg = &ptr; ?

Because &ptr has the wrong type. ptr has the type "array of three pointers
to char", so &ptr would have the type "pointer to array of three pointers
to char", whereas arg is not of this type or a compatible type.
I guess even more to the point, why is this legal?
arg = &(*ptr) ;

& and * cancel.
 
D

Dave Vandervies

I suspect I'm missing a broader concept here.

It looks to me like the broader concept you're missing is actually
pointers and arrays, not pointers to pointers.
You may find further enlightenment at
http://www.c-faq.com/aryptr/index.html
and at
http://groups.google.com/groups?q=group:comp.lang.c+author:"chris+torek"+"the+rule"

Okay, given the following
code:

#include <stdio.h>

int main(void) {
char *ptr[] = {"Garbage", "test", "work"};

ptr is an array of pointer to char with a slightly confusing name (since
it isn't actually a pointer).
Like any other array, it will be converted to a pointer to its first
element in most places you'll use it.
char **arg;

....and arg is a pointer to pointer to char, which can point at any element
of ptr[] (in particular, the first one that you get when you just say
`ptr' in a value context).
arg = ptr;

This does:
Convert ptr (array of pointer to char) into a pointer to its first
element (with type pointer to pointer to char).
Store that value in arg.
printf("The string is: %s\n", ptr[1]);
return 0;
}

Why am I not allowed to do something like:
arg = &ptr; ?

Giving it to the & operator like you're doing here is one of the
places where an array name *doesn't* get converted to a pointer[1].
The right-hand side of this assignment is a pointer to the array (with
type "pointer to array 3 of pointer to char"), and you're trying to
assign it to a pointer to pointer; since there's not a defined way to
convert from one of those types to the other (and not really a sensible
way either), the compiler complains.
I guess even more to the point, why is this legal?
arg = &(*ptr) ;

ptr gets converted to a pointer to its first element, and then you follow
that pointer, so the expression inside the parens identifies an object
of type pointer to char.
Then the & operator gives you a pointer to that object, with type
pointer to pointer to char. Since this is the same type of the object
you're storing it into, this works with no problems or complaints from
the compiler.

(This one is actually a special case of a more general rule: since & (get
pointer) and * (follow pointer) are inverse operations, saying "&(*p)"
will always give you the same value as just saying "p" for any pointer p,
and "*(&x)" will always give you the same object as just saying "x".)



Note that none of this actually needed us to know that ptr was an array
of pointers - everything would have worked the same way if it were, say,
an array of ints (as long as arg was a pointer the same type that ptr
was an array of). Pointers to pointers are just like pointers to any
other type: you can dereference a "foo *" to get a value of type "foo",
even if "foo" is a pointer type itself.



dave

[1] The other one you're likely to come across is when it's the operand
of the sizeof operator. I'm not going to complain that those are
the only two places it happens, but they're the only ones I can
recall ever having come across.
 
C

Chad

Dave said:
I suspect I'm missing a broader concept here.

It looks to me like the broader concept you're missing is actually
pointers and arrays, not pointers to pointers.
You may find further enlightenment at
http://www.c-faq.com/aryptr/index.html
and at
http://groups.google.com/groups?q=group:comp.lang.c+author:"chris+torek"+"the+rule"

Okay, given the following
code:

#include <stdio.h>

int main(void) {
char *ptr[] = {"Garbage", "test", "work"};

ptr is an array of pointer to char with a slightly confusing name (since
it isn't actually a pointer).
Like any other array, it will be converted to a pointer to its first
element in most places you'll use it.
char **arg;

...and arg is a pointer to pointer to char, which can point at any element
of ptr[] (in particular, the first one that you get when you just say
`ptr' in a value context).
arg = ptr;

This does:
Convert ptr (array of pointer to char) into a pointer to its first
element (with type pointer to pointer to char).
Store that value in arg.
printf("The string is: %s\n", ptr[1]);
return 0;
}

Why am I not allowed to do something like:
arg = &ptr; ?

Giving it to the & operator like you're doing here is one of the
places where an array name *doesn't* get converted to a pointer[1].
The right-hand side of this assignment is a pointer to the array (with
type "pointer to array 3 of pointer to char"), and you're trying to
assign it to a pointer to pointer; since there's not a defined way to
convert from one of those types to the other (and not really a sensible
way either), the compiler complains.

So in other words,
args = ptr;

could also be written as
args = &ptr[0]; ?

Chad
 
S

Skarmander

Dave said:
Chad <[email protected]> wrote:

ptr gets converted to a pointer to its first element, and then you follow
that pointer, so the expression inside the parens identifies an object
of type pointer to char.
Then the & operator gives you a pointer to that object, with type
pointer to pointer to char. Since this is the same type of the object
you're storing it into, this works with no problems or complaints from
the compiler.

(This one is actually a special case of a more general rule: since & (get
pointer) and * (follow pointer) are inverse operations, saying "&(*p)"
will always give you the same value as just saying "p" for any pointer p,
and "*(&x)" will always give you the same object as just saying "x".)
To be precise in a way that doesn't really matter but is still notable: this
is a direct consequence of how & is defined. In particular, the standard
guarantees that "&*p" is equivalent to "p" for *any* pointer p, even if p is
invalid, because the subexpression "*p" is not evaluated.

Some compilers actually get this wrong if optimization is not turned on, and
will insert evaluation of the pointer.

S.
 
S

Skarmander

Skarmander said:
To be precise in a way that doesn't really matter but is still notable:
this is a direct consequence of how & is defined. In particular, the
standard guarantees that "&*p" is equivalent to "p" for *any* pointer p,
even if p is invalid, because the subexpression "*p" is not evaluated.

Some compilers actually get this wrong if optimization is not turned on,
and will insert evaluation of the pointer.
Evaluation of the indirection, obviously.

S.
 
D

Dave Vandervies

Dave Vandervies wrote:

[much snippage]
So in other words,
args = ptr;

could also be written as
args = &ptr[0]; ?

Yes.
In the case of an array, the second version makes explicit what's being
done implicitly in the first version[1].

Somewhat confusingly (at least while you're still working on wrapping
your brain around it - once you Get It, it all makes perfect sense), even
if ptr were actually a pointer and not an array, these would still be
equivalent, since array indexing is defined in terms of pointer addition:
ptr[index]
is exactly equivalent to
*(ptr+index)
for any pointer (or array) ptr.
(And, of course, indexing with a pointer to a vector of objects works
the same way as indexing an array of objects.)

If you really want confusing, since pointer addition is commutative,
ptr[index] and *(ptr+index) are also equivalent to
*(index+ptr)
and therefore to
index[ptr]
- go ahead and try it out (just don't write serious code that uses this).


dave

[1] Actually, to be pedantically correct, it's doing something different-
but-with-identical-observable-effects. ptr is still being converted
from an array to a pointer to its first element, then indexing it
with [0] gives you that element, and then applying & gives you a
pointer to that element.
 

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

Similar Threads

pointers to pointers question 5
Pointers 16
problem to undestand nested pointers 1
pointers 4
Adding adressing of IPv6 to program 1
Array of structs function pointer 10
mastering pointers 17
int pointers & characters !! 17

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top