views:

519

answers:

5

Hi, I'm messing around with multidimensional arrays and pointers. I've been looking at a program that prints out the contents of, and addresses of, a simple array. Here's my array declaration:

int zippo[4][2] = { {2,4},
            {6,8},
            {1,3},
            {5,7}   };

My current understanding is that zippo is a pointer, and it can hold the address of a couple of other pointers. By default, zippo holds the address of pointer zippo[0], and it can also hold the addresses of pointers zippo[1], zippo[2], and zippo[3].

Now, take the following statement:

printf("zippo[0] = %p\n", zippo[0]);
printf("  *zippo = %p\n", *zippo);
printf("   zippo = %p\n", zippo);

On my machine, that gives the following output:

zippo[0] = 0x7fff170e2230
  *zippo = 0x7fff170e2230
   zippo = 0x7fff170e2230

I perfectly understand why zippo[0] and *zippo have the same value. They're both pointers, and they both store the address (by default) of the integer 2, or zippo[0][0]. But what is up with zippo also sharing the same memory address? Shouldn't zippo be storing the address of the pointer zippo[0]? Whaaaat?

+2  A: 

The important thing here is that int zippy[4][2] is not the same type of object as int **zippo.

Just like int zippi[5], zippy is the address of a block of memory. But the compiler knows that you want to address the eight memory location starting at zippy with a two dimensional syntax, but want to address the five memory location starting at zippi with a one dimensional syntax.

zippo is a different thing entirely. It holds the address of a a block of memory big enough to contain two pointer, and if you make them point at some arrays of integers, you can dereference them with the two dimensional array access syntax.

dmckee
+2  A: 
Alok
Let's see if I have this right: Even though `zippo` and `zippo[0]` point to different amounts of memory, their starting address is the same, and *in value contexts* they will both point to the first integer in zippo. Correct? And, is that what you mean by "decay"?
Ichimonji10
No. `zippo[0]` in value contexts is `int *`, and points to the first integer, where `zippo` in value contexts is "pointer to an array [2] of `int`". You could do: `int (*p)[2]; p = zippo;` for example. Then, `p[0] == 2` and `p[1] == 4`. For "decay", see my (soon to appear) edit.
Alok
+6  A: 

When you declare a multidimensional array, the compiler treats it as a single dimensional array. Multidimensional arrays are just an abstraction to make our life easier. You have a misunderstanding: This isn't one array pointing to 4 arrays, its always just a single contigous block of memory.

In your case, doing:

int zippo[4][2]

Is really the same as doing

int zippo[8]

With the math required for the 2D addressing handled for you by the compiler.

For details, see this tutorial on Arrays in C++.

This is very different than doing:

int** zippo

or

int* zippo[4]

In this case, you're making an array of four pointers, which could be allocated to other arrays.

Reed Copsey
Ahhh, this is a very clear explanation. Thanks. I'll do some reading on the difference between a simple multidimensional array (being a single, contiguous block of memory) and an array of pointers.
Ichimonji10
+2  A: 
John Bode
This really helps with my understanding of how many ways an array or pointer can be represented, and what it means for a statement to decay. Very thorough. Thanks.
Ichimonji10
A: 

Very well explained by Reed, I shall add few more points to make it simpler, when we refer to zippo or zippo[0] or zippo[0][0], we are still referring to the same base address of the array zippo. The reason being arrays are always contiguous block of memory and multidimensional arrays are multiple single dimension arrays continuously placed.

When you have to increment by each row, you need a pointer int *p = &zippo[0][0], and doing p++ increments the pointer by every row. In your example id its a 4 X 2 array, on doing p++ its, pointer currently points to second set of 4 elements.

Abhijit K Rao