Search code examples
carrayspointersextern

Extern pointer to variable vs array


I know this topic has been addressed a few times but I still don't get it.

Referring to http://c-faq.com/aryptr/aryptr2.html

char a[] = "hello";
char *p = "world";

creates an array "a". The variable is only a label of the address of the first memory address. p is a variable (== label of another memory address), containing the address of the first character (w - which may be somwhere else in the memory).

The thing I don't understand is the example from this topic (thanks!): using extern to link array with pointer :

extern1.c

extern int *array;
int test();

int main(int argc, char *argv[])
{
    printf ("in main: array address = %x\n", array);
    test();
    return 0;
}

extern2.c

int array[10] = {1, 2, 3};

int test()
{
    printf ("in test: array address = %x\n", array);
    return 0;
}

Why does the pointer variable "extern int *array" (== a label of memory address, containing an other address) in extern1 already contain the content of array[0]?

What is the difference to

int array[10] = {1, 2, 3};
int *ptrArrWorking = array; // == &array[0];

? In the extern case it would be something like

int array[10] = {1, 2, 3};
int *ptrArrNotWorking = array[0]; 

edit: to be more explicit let's interpret the example above as

int array[10] = {1, 2, 3};
int *ptrArrNotWorking = (int *)array[0]; 

so this simulates the same behaviour which can be seen in the extern example.

Where is the indirection hidden?

Thank you so much.


Solution

  • You have defined, in extern2.c, an object named array:

    int array[10] = {1, 2, 3};
    

    This is a contiguous segment of memory containing ten ints. Upon passing it to printf in test, it decays into a pointer to its first element -- that's how arrays are passed to functions. Thus, printf prints the address of the first int.

    In extern1.c, however, you lied when declaring array again:

    extern int *array;
    

    This pretends that array is a pointer, a single object which holds the address of something else. This mismatch renders the program "ill-formed, no diagnostic required". That was standardese for "badly broken" -- from then on there is no requirement on whether the program compiles, or what it actually does at runtime.

    In practice, the code following that broken declaration will indeed treat array as a pointer. So when you pass array to printf, it will chop off a handful of bytes from the beginning of the array (typically 4 or 8 depending on your platform), yell "there you go, here's the pointer" and give that to printf.

    Of course, it's not actually a valid pointer, but bits of the first few ints from array stuffed together, so what you see is nonsense.