Thread: array -- foo, &foo and &foo[0]

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    1,579

    array -- foo, &foo and &foo[0]

    Hello everyone,


    I think if we define foo as char array, for example,

    char foo [32];

    then foo, &foo and &foo[0] should be the same, right?

    For example, the following 3 statements are the same,

    strcpy (foo, goo);
    strcpy (&foo, goo);
    strcpy (&foo[0], goo);

    Any comments?

    I am very interested in how C treats foo and &foo and make them the same?


    thanks in advance,
    George

  2. #2
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    In terms of the how the computer hardware sees it, yes they are all the same, since they all resolve to the same address.

    In C, however, there is a distinction between arrays and pointers. This distinction is more theoretical but applies for matching of datatypes in certain expressions and passing of data around to functions.

    The value of all three expressions will be the same, however, in this case. The first is the array name and will be resolved as a pointer to the first element. The second one is the address of the array, which is resolved as a pointer to the first element. The last one is explicitly a pointer to the first element.

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    I want to confirm with you that you think the three items are the same, MacGyver?


    Quote Originally Posted by MacGyver View Post
    In terms of the how the computer hardware sees it, yes they are all the same, since they all resolve to the same address.

    In C, however, there is a distinction between arrays and pointers. This distinction is more theoretical but applies for matching of datatypes in certain expressions and passing of data around to functions.

    The value of all three expressions will be the same, however, in this case. The first is the array name and will be resolved as a pointer to the first element. The second one is the address of the array, which is resolved as a pointer to the first element. The last one is explicitly a pointer to the first element.

    regards,
    George

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    The second one is not the same as the others. It is of type char (*)[32], i.e. it is a pointer-pointer, and is not the same as the other two, which are just direct pointers.

    Proof: This compiles just fine:
    Code:
    if (foo == &foo[0]) {}
    but this doesn't:
    Code:
    if (&foo == &foo[0]) {}
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #5
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    If foo is declared as an array, not as a pointer, then they are the same. But if foo is declared as a pointer, then the second is the address of the pointer (pointer to the pointer). Proof of concept:
    Code:
    #include <stdio.h>
    
    int main(int argc, char *argv[]){
        char* pointer=(char*)malloc(4);
        char array[4];
        printf("pointer = &#37;d, &pointer = %d, &pointer[0] = %d\n",pointer,&pointer,&pointer[0]);
        printf("array = %d, &array = %d, &array[0] = %d\n",array,&array,&array[0]);
        free(pointer);
        getchar();
        return 0;
    }
    Sample output:
    Code:
    pointer = 4007032, &pointer = 2293620, &pointer[0] = 4007032
    array = 2293616, &array = 2293616, &array[0] = 2293616
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  6. #6
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Quote Originally Posted by George2 View Post
    I want to confirm with you that you think the three items are the same, MacGyver?
    If you mean, "Do they all refer to the same address?" then yes.

    If you mean, "Will my C compiler allow me to interchange those notations at will?" No. In terms of the type of the variable behind each notation, one or more might be different.

    Experiment a bit with this stuff. It may be hard to find cases earlier on where the notation matters, but you'll probably start to notice it when you get into multidimensional arrays and passing them around into functions and such.

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Err, maxorator? return is a keyword too, you know. Or did you only highlight data types like int?

    I am very interested in how C treats foo and &foo and make them the same?
    The only case in which your statement is true is when you're talking about function pointers, but that's another kettle of fish.

    foo is the same as &foo[0] for any array, however. Or any pointer. Using pointer syntax, it's the same as &(*(foo + 0)), which is the same as &*foo, which is the same as foo when *foo is valid; i.e., it doesn't work for ints.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  8. #8
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Code:
        printf("pointer = %p, &pointer = %p, &pointer[0] = %p\n", (void*)pointer, (void*)&pointer, (void*)&pointer[0]);
        printf("array = %p, &array = %p, &array[0] = %p\n", (void*)array, (void*)&array, (void*)&array[0]);

  9. #9
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by George2 View Post
    I am very interested in how C treats foo and &foo and make them the same?
    It has been pointed out that these two items will have same value, however they are not the same.


    For an array of "anything":

    The name of the array used by itself (no [] brackets) is taken to be a const pointer to "anything", whose value is the address of the first element of the array.

    Therefore if "foo" is an array of char, "foo" and "&foo[0]" are treated the same way: foo is a pointer to char, &foo[0] is a pointer to char. The notation for foo and &foo[0] is interchangeable.

    However, if foo is an array of, say, 100 chars, then &foo is a pointer to an array of 100 chars. That is not the same as a pointer to char.

    Consider the following:

    Code:
    #include <stdio.h>
    
    int main()
    {
        char foo[100];
        char *p1;
        char *p2;
        char *p3;
        char (*p4)[100]; /* a pointer to an array of 100 chars */
    
        p1 = foo;
        p2 = &foo[0];
        p3 = &foo;
        p4 = &foo;
    
        printf("p1 = &#37;p, p1+1 = %p\n", (void *)p1, (void *)(p1+1));
        printf("p2 = %p, p2+1 = %p\n", (void *)p2, (void *)(p2+1));
        printf("p3 = %p, p3+1 = %p\n", (void *)p3, (void *)(p3+1));
        printf("p4 = %p, p4+1 = %p\n", (void *)p4, (void *)(p4+1));
    
        return 0;
    }
    Now, with gcc, the assignment statement for p3 is flagged with a "warning: assignment from incompatible pointer type". Since it's only a warning, an executable is generated.

    The output is:

    Code:
    p1 = 0xbfa160c0, p1+1 = 0xbfa160c1
    p2 = 0xbfa160c0, p2+1 = 0xbfa160c1
    p3 = 0xbfa160c0, p3+1 = 0xbfa160c1
    p4 = 0xbfa160c0, p4+1 = 0xbfa16124
    So, used this way, we can see that, indeed, the value of the value of the address of the array is equal to the value of the address of the first element of the array. (What else would it be?)

    However---look at the result of pointer arithmetic for p4. The value of p4+1 is 100 (decimal) larger than the value of p4.

    One further note:

    If you try to compile this program with g++, the compiler flags the assignment statement for p3 with " error: cannot convert ‘char (*)[100]’ to ‘char*’ in assignment." and no executable is created. In other words, C++ is a little more picky about what it lets you do with pointers. (Requires an explicit reinterpret_cast. That's a good thing, right?) Removing the assignment and print statements for p3 results in a clean compile with gcc as well as with g++, and, of course, the results are the same.


    Bottom line: Sloppy or unknowing C programmers who use "&foo" instead of "foo" or "&foo[0]" may actually get something that does what they want it to do (for example, strcpy() works the same), but why would you do such a thing, knowing what this simple example tells us? Namely that they are not the same, and, depending on how you use them, you could get different results.

    D
    Last edited by Dave Evans; 08-14-2007 at 12:55 PM.

  10. #10
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Yeah sorry, I was actually using a C++ compiler.

    Nice summary Dave.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed