17

Given that the name of an array is actually a pointer to the first element of an array, the following code:

#include <stdio.h>

int main(void)
{
    int a[3] = {0, 1, 2};
    int *p;

    p = a;

    printf("%d\n", p[1]);

    return 0;
}

prints 1, as expected.

Now, given that I can create a pointer that points to a pointer, I wrote the following:

#include <stdio.h>                                                              

int main(void)                                                                  
{                                                                               
        int *p0;                                                                
        int **p1;                                                               
        int (*p2)[3];                                                           
        int a[3] = {0, 1, 2};                                                   

        p0 = a;                                                                 
        p1 = &a;                                                                
        p2 = &a;                                                                

        printf("p0[1] = %d\n(*p1)[1] = %d\n(*p2)[1] = %d\n",                    
                        p0[1], (*p1)[1], (*p2)[1]);                             

        return 0;                                                               
}

I expected it to compile and print

p0[1] = 1
(*p1)[1] = 1
(*p2)[1] = 1

But instead, it goes wrong at compile time, saying:

test.c: In function ‘main’:
test.c:11:5: warning: assignment from incompatible pointer type [enabled by default]

Why is that assignment wrong? If p1 is a pointer to a pointer to an int and a is a pointer to an int (because it's the name of an array of ints), why can't I assign &a to p1?

Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
jpmelos
  • 3,283
  • 3
  • 23
  • 30
  • 1
    Sometime ago I wrote [an answer to a similar question](http://stackoverflow.com/questions/5181237/confusion-in-data-types-in-a-2d-array) you might like. – pmg Jun 24 '11 at 22:13

3 Answers3

21

Line 11 is

        p1 = &a;

where p1 has type int ** and a has type int[3], right?

Well; &a has type int(*)[3] and that type is not compatible with int** as the compiler told you

You may want to try

        p1 = &p0;

And read the c-faq, particularly section 6.

In short: arrays are not pointers, and pointers are not arrays.

pmg
  • 106,608
  • 13
  • 126
  • 198
  • 2
    That kind of subverts everything I thought I knew about arrays and pointers. I'm wondered by how did I get away with this for so many years, really. Thank you for making it clear. – jpmelos Jun 24 '11 at 21:58
  • 1
    @jpmelos - The way arrays and pointers work is surprisingly subtle, and not something that's very easy to make clear early on in learning C. Glad you got it. – Chris Lutz Jun 24 '11 at 22:01
  • 1
    You got away with it because very often arrays behave as pointers and pointers behave as arrays ... **but they're not the same!** Read [the c-faq](http://c-faq.com/) section 6: it's really interesting :) – pmg Jun 24 '11 at 22:02
7

a is not a pointer to int, it decays to such in certain situations. If &a was of type int ** you couldn't very well use it to initialize p2, could you?

You need to do p1 = &p0; for the effect you want. "pointer to pointer" means "at this address, you will find a pointer". But if you look at the address &a, you find an array (obviously), so int ** is not the correct type.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • Then, what is stored under the name `a`, if not an address to the first element of `a` (which would be the pointer I was looking for)? – jpmelos Jun 24 '11 at 21:54
  • 3
    @jpmelos - `a` is an array. It stores the actual array elements. The name of an array decays to a pointer to the first element when passed to a function, but that doesn't mean that arrays are implemented as pointers to an area. `int a[3];` on its own makes no pointers, just three `int`s. – Chris Lutz Jun 24 '11 at 21:57
  • Thank you very much! Your comment helped me enlighten my thoughts a little bit further! – jpmelos Jun 24 '11 at 22:06
0

For many operations, a implies &a and both return the same thing: The address of the first item in the array.

You cannot get the address of the pointer because the variable does not store the pointer. a is not a pointer, even though it behaves like one in some cases.

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466