1

Possible Duplicate:
How are two-dimensional arrays formatted in memory?

int map[3][3] = {1,2,3,4,5,6,7,8,9};
int **p = map;
printf( "%d", *p+1 );

Can someone tell me why the result is 5 ? And if

printf( "%d", *p+2);

the result is 9 ? (compiled by Visual C++)

Community
  • 1
  • 1
xhlwill
  • 399
  • 1
  • 5
  • 20

2 Answers2

3

Because arrays are not pointers. A double pointer isn't equivalent to a two-dimensional array, since arrays are contigous in memory. Your array is created and filled with data as follows:

map[0][0] = 1
map[0][1] = 2
map[0][2] = 3
map[1][0] = 4
map[1][1] = 5
map[1][2] = 6
map[2][0] = 7
map[2][1] = 8
map[2][2] = 9

When you're assigning this to a double pointer, then you're doing several things wrong. For example:

printf("%d", *p + 1);

doesn't do what you think it does. It's undefined behavior since the type of *p is int * but the %d format specifier expects an int. Basically, don't try to treat arrays the same as pointer, because they're not the same. Please read the relevant part of the C FAQ in order to understand how to correctly handle such a situation. Basically, it would suffice to use a one-dimensional pointer in this case and index it properly.

Demonstration:

enter image description here

  • I originally downvoted you because you said they could be accessed linearly using a simple pointer. This was incorrect. You updated your answer to include that they have to be referenced as array of arrays and I removed my downvote. – devshorts Oct 12 '12 at 18:07
  • @devshorts no, that was not incorrect. If you assign the base address of the array to a single-pointer, it will work. You were trying to get that working but you only thought about the array and not the pointer. And 'must reference them as array of arrays' isn't even in my answer. –  Oct 12 '12 at 18:16
  • It wasn't in the answer but at the time thats what your example was effectively doing. I appreciate you revising your answer though – devshorts Oct 12 '12 at 18:17
  • 2
    In your edit, you screwed up the indices in the code block, they were correct before, they're wrong now (twice `map[1][2]`, and `map[2][3]` instead of `map[2][1]`). – Daniel Fischer Oct 12 '12 at 18:27
  • @DanielFischer Hell, I honestly haven't touched that part! Thanks for pointing out this, fixed now. Also, the link to the image and the C FAQ were screwed up, too! (What's going on?) –  Oct 12 '12 at 18:30
3

To amend to H2C03's answer...

Your first deref takes you into the array 1 dimmension. Specifically it leaves you pointing at the entry for '1'.

What most people here don't seem to entirely have figured out is what's happening next. At this point 'p' is still considered a pointer. It believe it contains the address '1'. When you do the '+1' you are actually getting pointer arithmetic. Since sizeof(int) is (typically) 4, you are simply printing the first element of the matrix +4. Thus +2 converts to +8 since pointer arithmetic is always done in terms of the size of the 'thing' the pointer points at. And so you get 5 and 9.

A quick disasm of the code will show.

mov eax, DWORD PTR ?p@@3PAPAHA      ; p
mov ecx, DWORD PTR [eax]            ; deref of p (which is '1')
add ecx, 4                          ; let's just +4 it and push it as the arg to printf
push    ecx
push    OFFSET $SG3670
call    _printf
Joe
  • 2,946
  • 18
  • 17