Vivek Maran
Vivek Maran

Reputation: 2753

Pointers with two dimensional array

Please consider the following piece of code

#include <stdio.h>
#define ROW_SIZE 2
#define COL_SIZE 2

int main()
{
   int a[ROW_SIZE][COL_SIZE]={{1,2},{3,4}};

   // Base address:Pointer to the first element a 1D array
   printf("Base address of array:%p\n",a);

   //The value at the base address: should be the address of 1st 1D array
   printf("Value at the Base address:%p\n",*a);

   return 0;
}

Output obtained:

Sample Output:
Base address of array:0xbff77434
Value at the Base address:0xbff77434

Somehow, I am failing to understand the concept of the base address of a 2D array and the value at the base address which is inturn an address to a 1D array being same. Please explain.

Upvotes: 4

Views: 8228

Answers (4)

npclaudiu
npclaudiu

Reputation: 2451

The bidimensional array a[2][2] can be seen as a monodimensional array with 4 elements. Think what happens when you cast a to an int* pointer:

int a[2][2] = {{ 1, 2 }, { 3, 4 }};
int* p = (int*) a; // == { 1, 2, 3, 4 }

assert(a[1][0] == p[2] == 3); // true

int* a0 = a[0];  // the first row in the bidimensional array
int* p0 = &p[0]; // the first element in the monodimensional array

assert(*a0 == *p0 == 1); // true

// Or the long version:
assert(a[0][0] == *a0 == a0[0] == p[0] == *p0 == p0[0] == 1); // true

// And for the second array in a:
int* a1 = a[1]; // the second row in the bidimensional array
int p2 = &p[2]; // the third element in the monodimensional array

assert(a[1][0] == *a1 == a1[0] == p[2] == *p2 == p2[0] == 3); // true

The arrays a and a[0] basically point to the same address, but their types convey informations about how they can be manipulated.

Upvotes: 0

Vivek Maran
Vivek Maran

Reputation: 2753

Re-structuring the diagram in the question and consolidating the information from previous answers, I am creating the following answer.

Arrays and pointers

One dimensional array

  • Consider an array a of 4 integers as a[4]
  • Basic rule is both a and &a will point to same location.But they aren't pointing to the same type.
  • &a will point to the entire array which is an int[]. The pointer type is int(*)[]
  • a, when it decays to a pointer, will point to the first element of the array which is an int. The pointer type is int *

Two dimensional array

  • Consider an array containing two 1D arrays, with each of them having two elements ;a[2][2].
  • Since the number of dimensions increases, we have one more level of hierarchy i.e. &a,a and *a will point to same location, but they aren't pointing to the same type.
  • &a will point to the entire array which is int[][]. The pointer type is int(*)[][].
  • a, when it decays to a pointer, will point to the first element of the 2D array which is an int[]. The pointer type is int(*)[]
  • By using *a, we are de-referencing the pointer to a 1D array. Hence we will have a int * pointing to the first integer value of the 2D array.

Upvotes: 7

Mark Stevens
Mark Stevens

Reputation: 2366

I think the formatting of your output is throwing you. You are right, the address of the first array element (0xbff77434) is different from the value (1). The %p is getting confused trying to force both to a "pointer" format.

And yes, Carl's correct too.

If you want to see what's at the first element, you would say any of these:

printf("%i", a[0][0]);

int* p = &a[0][0];    // point 'p' to the beginning of 'a'
// (or)
int* p = a;           // saying "&a[0][0]" is the same as saying "a"
printf("%i", *p);     // here, the dereference is what you want

As far as 1D vs 2D arrays, it's just a matter of interpretation. Both

int x[4];

and

int x[2][2];

create contiguous blocks of 4 'int-sized' elements. And in both cases, the expression 'x' refers to the address of the 0th entry (eg, the address of the array).

Upvotes: 0

Carl Norum
Carl Norum

Reputation: 225242

Arrays aren't pointers, and in C, a multidimensional array is just an array of arrays. In many contexts, using the name of an array "decays" into a pointer to the first element of that array. That's what happens in both of your print statements. In the first case:

printf("Base address of array:%p\n",a);

a becomes a pointer to the first element of the array - that is, a pointer to the first row of your array. In your case, that means you get a pointer of type int (*)[2].

In the second case:

printf("Value at the Base address:%p\n",*a);

The same decaying happens, but then you dereference that pointer. That means you dereferenced that int (*)[2] pointer to the first row, leaving you with an array again (the first row). That array itself decays into a pointer to its first element, giving you a resulting int * pointer (to the first element of the first row).

In both cases the address is the same, since that's how the array is laid out in memory. If we said your 2D array started at address 0, it would look like this (assuming a 4 byte int type):

 Address       Value
    0            1
    4            2
    8            3
   12            4

The address of the first row and the address of the first element of the first row are both 0.

Upvotes: 8

Related Questions