2

I am surprised to see this code segment print the same address for all the three pointers.

int main(int argc,char *argv[]) { int arr[3][3]; printf("%p\n%p\n%p\n",arr,*arr,arr[0]); return 0; } 

Why this is so ?

1
  • did it print something like 0xfefefefe or 0xcdcdcdcd ? Commented Oct 13, 2010 at 23:22

4 Answers 4

4

See So what is meant by the ``equivalence of pointers and arrays'' in C?

The address of an array is the address of its first element. And, arr[i] is equivalent to *(arr + i) for any array arr. Therefore, arr[0] is the same as *(a + 0).

Sign up to request clarification or add additional context in comments.

1 Comment

arr[0] = *arr for all arrays that should have been the obvious bit. The surprising change for multidimensional arrays is that arr = *arr which only holds for multi-dimensional arrays due to how C treats them and lays them out in memory.
3

Because an array's address is equal to the starting element's address.

Which means, address of arr[1] is equal to address of arr + 1 and address of *(arr + 1).

5 Comments

Its wrong but I'm not downvoting because of the unexplained downvotes. arr[1] is not equivalent to arr + 1 nor *arr + 1 but rather *(arr + 1)
An array does not always point to the initial element, for example if it is the operand of the unary & or sizeof operators.
@mathepic, in terms of printing %p, it is. Not talking about the values though, editing my answer.
@dreamlax, Address of &arr[0] is equal to arr.
@Ruel: That's because the subscript operator takes precedence and therefore the operand to the unary & has type int. If you did (&arr)[1] you'll find that it points passed all of the elements of arr.
3

C lays out multidimentional arrays flat if at least all but the last dimension is known at compile time - so an int[3][3] is actually just and int[9] array in memory - only the type is different.

So, since an array is silently converted to a pointer to its first element when used in most expressions *arr is always equivalent to arr[0] for all arrays. In this instance, arr (two levels of indirection to int) is a pointer to the first int[3] array, *arr==arr[0] (1 level of indirection to int) is a pointer to the first integer in the first int[3] array, since the whole structure is 'flat' this first int[3] starts at exactly the same place as the int[3][3] array.

Its a little confusing, but in memory it is just 9 integers in a row that the compiler 'knows' should be treated as blocks of 3

if the cells are those shown below:

|0|1|2|3|4|5|6|7|8| 

then arr is a pointer to |0|, arr+1 is a pointer to |3| and arr+2 is a pointer to |6|

arr[0] is ALSO a pointer to |0|, arr[0]+1 is a pointer to |1|, arr[0]+2 is a pointer to |2| and so on... Since arr[0] is always identical to *arr for any array, *arr is ALSO a pointer to |0|

10 Comments

This is not true. An array is not just a pointer to its first element. When used in an expression and when not an operand of the unary & and sizeof operators, it is converted to a pointer type pointing to the initial element of the array.
True, sizeof does treat arrays specially, but when dereferencing using the unary * operator it is safe to assume as much. Effectively an array is a pointer with some compile-time-only metadata that the compiler can use to evaluate some pseudo-functions like sizeof
Your statement is still incorrect. In C99 the sizeof operator must also return the size of a variable length array. sizeof is not a pseudo-function it is an operator. An array is converted to a pointer type pointing to its initial element (see §6.3.2.1 paragraph 3 of the C standard).
arr is only converted to a pointer type when it is used in an expression and when it is not the operand of & or sizeof. For example, an array is a non-modifiable lvalue. If it were a pointer, it could be assigned to, but you can't assign an array to another array (i.e. you can't do arr = {{0,1,2},{3,4,5},{6,7,8}};).
you are right, i apologise... i hadn't thought about that... still, in terms of dereferencing the array i.e. the only 2 operators used on it are subscript and unary * it is effectively just a pointer.
|
1

arr is the address of the first element in the array which is also the address of the first row of the array due to how C lays out multidimensional arrays in memory.

arr[0] returns a pointer to the first row so is equivalent to arr

*arr = arr[0] as with all C pointers

basically they are all the same because of the way C lays out multidimensional arrays, the address of the beginning of the array is also the address of the first row of the array.

part of this confusion is that while for a 1 dimensional array, arr[], arr can be treated as a pointer as if it were defined '*arr'. This isn't true for multidimensional arrays. arr[][] can't be treated as a double pointer, as if it were defined **arr. they are very different data types.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.