(*p)[4] is not a double pointer declaration, nor is it "cheating". You simply aren't reading/understanding the type of p correctly in your first example. Declared on a line of it's own, it looks like this:
p is a pointer to array of 4 ints. That is different from a pointer to pointer to int. Arrays and pointers are not equivalent. See here: Arrays and Pointers, particularly 6.1-6.4b, and 6.8-6.13. Also, for help reading complex type declarations, I find this link helpful: Arrays and Pointers. There was another good link posted a few weeks back, but I can't find it.
Now, in the first post, since p is a pointer to array of 4 ints, doing p++ increases the address by sizeof(array of 4 ints), or 4*sizeof(int). In the second post, p is a pointer to int, so p++ increments it by sizeof(int), not (#COLUMNS * sizeof(int)).
Print out the relevant sizes of what p points to, ints, array rows, etc to help you understand. For snippet 1:
Code:
printf("sizeof(int) = %d\n", sizeof(int));
printf("sizeof(*p) (i.e. the size of what p points to) = %d\n", sizeof(*p));
printf("sizeof(arr2d[0]) = %d\n", sizeof(arr2d[0]));
for( p = &arr2d[0]; p < &arr2d[2]; p++)
{
printf("p = %p (*p)[i] = %d arr2d[0][0] = %d\n" , (*p)[i] , arr2d[0][0] );
}
Compile and run:
Code:
sizeof(int) = 4
sizeof(*p) (i.e. the size of what p points to) = 16
sizeof(arr2d[0]) = 16
p = 0xbfb9c9c8 (*p)[i] = 0 arr2d[0][0] = 0
p = 0xbfb9c9d8 (*p)[i] = 4 arr2d[0][0] = 0
Notice p increments by 16, the size of 4 ints, or one row in a 2-d array with 4 columns per row.
For snippet 2:
Code:
printf("sizeof(int) = %d\n", sizeof(int));
for( p = arr2d[0]; p < arr2d[1] + 4 ; p++)
{
printf("p = %p, *p = %d\n" , (void *)p, *p );
}
Output:
Code:
sizeof(int) = 4
p = 0xbf991bbc, *p = 0
p = 0xbf991bc0, *p = 1
p = 0xbf991bc4, *p = 2
p = 0xbf991bc8, *p = 3
p = 0xbf991bcc, *p = 4
p = 0xbf991bd0, *p = 5
p = 0xbf991bd4, *p = 6
p = 0xbf991bd8, *p = 7
Notice that p increments by 4 bytes only, the size of one single int.