sksingh
sksingh

Reputation: 27

Multidimensional array addressing C

In the following piece of code, I am getting the first two values of addresses same(call it x). I have run it on gcc compiler of ubuntu v18.04.4 LTS.

  int a[2][2] = {0};
  printf("%p %p %d\n", a, *a, **a);

This mean that:

  1. a contains the address x.
  2. a is pointing to the location x(as it is a pointer which is storing x).
  3. this means *a is stored in location x and it also contains the value x(as in the output of above code).
  4. now, on dereferncing *a i.e, **a, I am getting output as 0 which means that *a (whose value is x) is pointing to some location in which 0 is stored.

Now, from 1. , address of *a is x (as a points to *a and is storing x) and address of the number 0 is also x (as *a points to a[0][0] which is 0 and *a is storing x). So my question is what exactly is stored at the location x? Or have I mistaken something in making the conclusions?

Upvotes: 1

Views: 98

Answers (2)

dbush
dbush

Reputation: 223872

Your assertion that a contains an address seems to indicate that you think a is a pointer. It is not a pointer but an array. They are related, but they are not the same thing.

An array, in most contexts, decays to a pointer to its first member. In this case, this means that in an expression a is the same as &a[0] and *a is the same as a[0] which is the same as &a[0][0]. This also means that the address of an array is the same as the address of its first member, which is what you're seeing when you print a and *a.

This would probably be better illustrated with a diagram:

      -----   -------   ----  ---
0x100 | 0 |   a[0][0]   a[0]  a
      -----   -------   
0x104 | 0 |   a[0][1]
      -----   -------   ----
0x108 | 0 |   a[1][0]   a[1]
      -----   -------
0x10c | 0 |   a[1][1]
      -----   -------   ----  ---

From here, you can see that a starts at address 0x100 (x in your example) and contains a total of 4 int values. Also note that the subarray a[0] has the same address as a, as does the initial int element a[0][0].

Generalizing this, the address of an array and the address of its first element, even though the types are different, are the same. So:

  • a is an array whose address is 0x100. It contains element of type int[2].
  • a[0] is an array whose address is 0x100. It contains element of type int.
  • a[0][0] is an int whose address is 0x100.

Upvotes: 2

Vlad from Moscow
Vlad from Moscow

Reputation: 310980

I have not understood what is the magic 'x'.;)

You declared a two-dimensional array

int a[2][2] = {0};

Array designators used in expressions (with rare exceptions as for example using them in the sizeof operator) are implicitly converted to pointers to their first elements.

So the expression a used in this call

printf("%p %p %d\n", a, *a, **a);

is converted to the pointer of the type int ( * )[2] to the first element of the array. That is it is the address of the memory extent occupied by the array.

Using the indirection operator * the expression *a yields the first element of the type int[2] of the original array a.

Again this array designator *a in the call of printf is implicitly converted to pointer of the type int * to its first element that has the type int. This pointer will contain the same address of the memory extent occupied by the original array.

In this expression **a there are applied two indirection operators. The first indirection operator yields the first element of the two-dimensional array that is it yields an array of the type int[2]. This array used as an operand of the second indirection operator at once is implicitly converted to pointer to its first element that has the type int *. The second indirection operator yields the object pointed to by the pointer that is the object of the original array a[0][0] that is outputted by the printf call shown above. As this element was explicitly initialized by 0 then 0 is outputted as the value of the element.

To make it more clear the first indirection operator *a is equivalent to using the subscript operator a[0]. And the second indirection operator applied to this expression *a[0] is equivalent to the expression a[0][0].

Upvotes: 2

Related Questions