Heng Wei
Heng Wei

Reputation: 209

Dereferencing a pointer to 2d array

I don't understand why when dereferencing a pointer to an array, the result is the address of the first value of the array

int array[2][2] = {{0,1},{0,1}}; 
int (*p)[2];
p = array;

p = address of a[0][0], p+1 = address of a[1][0], 
*p = address of a[0][0], (*p)+1 = the address of a[0][1];

I understand that p is a pointer to an array of 2 integers, not a pointer to an integer. But if we print out the value of p, it's still the address of an integer. I want to know what's going on under the hood? Is p a pointer to an array of pointers? So we have to dereference it twice to get the value of the integer its pointing?

A pointer to an int,

int* p;

is a variable, stored in a location, that contains the address of another variable (int).

When we dereference it, we get the value of that variable. How does this process work exactly with a pointer to an array?

Upvotes: 1

Views: 3548

Answers (2)

Krishna Kanth Yenumula
Krishna Kanth Yenumula

Reputation: 2567

  1. Value at an array can be accessed using
    array[i] = *(array+i) (expansion of [i]).

  2. Similarily, (*p)[i] = *(*(p+i)). So, we need to dereference twice to access the value.

  3. If you want to access, array[0][0], you have to use *(*(p+0)+0) = **p;, Similarily, array[0][1] can be accessed using *(*(p+0)+1) = *((*p)+1);

  4. Note, *p points to first row (stores address of array[0][0]), and *(p+1) points to second row (stores address of array[1][0]).

Please check the below code :

#include <stdio.h>
int main()
{
    int array[2][2] = {{1, 2}, {3, 4}};
    int(*p)[2];
    p = array;


    printf("The address of array[0][0] is %p \n",&array[0][0]);
    printf("The address of *p is %p \n",*p);

    printf("The address of array[1][0] is %p \n",&array[1][0]);
    printf("The address of *(p+1) is %p \n",*(p+1));

    printf("The value of array[0][0] is %d \n",array[0][0]);
    printf("The value of **p is %d \n",**p);

    printf("The value of array[0][1] is %d \n",array[0][1]);
    printf("The value of *((*p)+1) is %d \n",*((*p)+1));


    return 0;
}

The output is:

The address of array[0][0] is 0x7fff6e8781a0 
The address of *p is 0x7fff6e8781a0 
The address of array[1][0] is 0x7fff6e8781a8 
The address of *(p+1) is 0x7fff6e8781a8 
The value of array[0][0] is 1 
The value of **p is 1 
The value of array[0][1] is 2 
The value of *((*p)+1) is 2 

Upvotes: 1

Eric Postpischil
Eric Postpischil

Reputation: 224310

The address of an array is the same as the address of its first element.

Given the definition int array[2][2] = {{0,1},{0,1}};, the compiler arranges some location in memory to contain the int values 0, 1, 0, and 1. Let’s say that location has address 1000, and the int value 0 is stored in bytes 1000-1003, 1 is stored in 1004 to 1007, 0 is stored in 1008 to 1011, and 1 is stored in 1012 to 1015.

Where does the element array[0][0] start in memory? At location 1000.

Where does the array array start in memory? At location 1000.

Where does the array array[0] start in memory? At location 1000.

The array starts in memory at the same location its first element starts in memory. Also, array[0], which is itself an array, starts at the location 1000.

So, after p = array;, p points the location 1000. And the element array[0][0] also starts at location 1000. So, when you print p, as with printf("%p\n", (void *) p);, it is unsurprising you get the same result as when you print the address of array[0][0], as with printf("%p\n", (void *) &array[0][0]);.

An array is automatically converted to the address of its first element.

Next, let’s consider *p. The type of p is int (*)[2], a pointer to an array of 2 int. Therefore, *p is an array of 2 int.

In particular, *p is an array. Suppose we attempt to print it by passing it as an argument to printf. What happens?

In C, when an array is used in an expression, it is automatically converted to the address of its first element (except when the array is the operand of sizeof or unary & or is a string literal used to initialize an array). So, if you use *p as an argument to printf, it initially means array[0], but that array is converted to the address of its first argument. So passing *p as an argument actually passes &array[0][0] (or, equivalently &(*p)[0]).

Thus, printf("%p\n", (void *) *p); will print the same address as printf("%p\n", (void *) &a[0][0]);.

Upvotes: 4

Related Questions