More on pointers to pointers.

Discussion in 'C Programming' started by Chad, Mar 31, 2006.

  1. Chad

    Chad Guest

    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
    Chad, Mar 31, 2006
    #1
    1. Advertising

  2. 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.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
    Richard Heathfield, Mar 31, 2006
    #2
    1. Advertising

  3. In article <>,
    Chad <> wrote:
    >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.

    --
    Dave Vandervies
    If parachutes were maintained to the same standards as the typical car
    you'd have parachutists dropping out of the skies like flies.
    --Bram in the scary devil monastery
    Dave Vandervies, Mar 31, 2006
    #3
  4. Chad

    Chad Guest

    Dave Vandervies wrote:
    > In article <>,
    > Chad <> wrote:
    > >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
    Chad, Mar 31, 2006
    #4
  5. Chad

    Skarmander Guest

    Dave Vandervies wrote:
    > In article <>,
    > Chad <> wrote:

    <snip>
    >> 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".)
    >

    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.
    Skarmander, Mar 31, 2006
    #5
  6. Chad

    Skarmander Guest

    Skarmander wrote:
    > Dave Vandervies wrote:
    >> In article <>,
    >> Chad <> wrote:

    > <snip>
    >>> 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".)
    >>

    > 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.
    Skarmander, Mar 31, 2006
    #6
  7. In article <>,
    Chad <> wrote:
    >
    >Dave Vandervies wrote:


    >> 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.


    [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.

    --
    Dave Vandervies
    It is two statements. If enclosed by {} it would be one statement,
    which happens to be compound, and to consist of two statements.
    --CBFalconer in comp.lang.c
    Dave Vandervies, Apr 1, 2006
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. shess
    Replies:
    0
    Views:
    281
    shess
    Nov 24, 2003
  2. Michael
    Replies:
    4
    Views:
    399
    Matt Hammond
    Jun 26, 2006
  3. AW på ZRX

    Applet uses more and more CPU.

    AW på ZRX, Sep 11, 2006, in forum: Java
    Replies:
    3
    Views:
    358
    Tris Orendorff
    Sep 13, 2006
  4. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    656
  5. Robert Klemme

    With a Ruby Yell: more, more more!

    Robert Klemme, Sep 28, 2005, in forum: Ruby
    Replies:
    5
    Views:
    204
    Jeff Wood
    Sep 29, 2005
Loading...

Share This Page