Why does C program crash when dereferencing pointer to an array?

2

I have a simple C code:

int main()
{
    int test[10] = {1,2,3,4,5,6,7,8,9,10};
    int **ptr = &test;

    printf("%d\n", (*ptr)[0]);

    return 0;
}

As soon as it reaches the printf line, it crashes:

Process returned -1073741819 (0xC0000005)   execution time : 0.865 s

When compiling the code on Ubuntu, it gives me the warning:

test.c:8:17: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
     int **ptr = &test;

However, if I instead dynamically allocate the memory on the heap, the code works:

int main()
{
    int *test = malloc(sizeof(int)*10);
    for (int i = 0; i < 10; i++) {
        test[i]=i;
    }
    int **ptr = &test;

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

    return 0;
}

Please explain to me, why the code works when the array is on the heap, but not on the stack?

c
windows
pointers
mingw
double-pointer
asked on Stack Overflow Jan 26, 2020 by Victor2748 • edited Jan 26, 2020 by Victor2748

1 Answer

2

In order to get your ptr variable to be the "address of an array of integers" you actually need a rather more subtle (and arcane) declaration.

This will work:

int (*ptr)[10] = &test;

as it declares that, when dereferenced (i.e. when you then actually use the expression *ptr), it will be an array (of 10 elements).

In some ways, the structure of the declaration is a bit like that for pointers-to-functions.

EDIT: In your second case, test is a plain old pointer (with a value assigned to it by the malloc call); as such, it is itself a variable whose address can be taken (as your int **ptr = &test; line does - correctly).

However, in the first case ('fixed' array), test refers to a block of memory; in many ways, this can be used as a pointer to the first element (like it will be in a function call, for example). But what value can the compiler possibly assign to the "address of the address of the first element?" This is what fails in the attempted assignment using &test in this case.

But, you would be entitled to ask, according to the previous paragraph, how does the compiler determine a value for &test (to assign to ptr) with the code given in this answer? Well, if you add the following line to your program:

printf("%p %p\n", test, &test);

you will see that test and &test (you can change &test for ptr - the output will be the same) have exactly the same value! Thus, using this 'arcane' declaration, you give the compiler enough information to know what to do with the "array pointer" - basically, it sort of 'ignores' (or bypasses) the first level of dereferencing, ending up with the address of the array's first element (as is).

answered on Stack Overflow Jan 26, 2020 by Adrian Mole • edited Jan 27, 2020 by Adrian Mole

User contributions licensed under CC BY-SA 3.0