What is the difference between these 2 prints, I got the same address in both of them :
int main(void)
{
int arr[2][3] = {{1,2,3},{4,5,6}};
printf("%p\n", arr);
printf("%p\n", *(arr));
}
What is the difference between these 2 prints, I got the same address in both of them :
int main(void)
{
int arr[2][3] = {{1,2,3},{4,5,6}};
printf("%p\n", arr);
printf("%p\n", *(arr));
}
arr
is an array of 2 arrays of a 3 int
. Consider these three things:
arr
.arr
, also called arr[0]
.arr[0]
, also called arr[0][0]
.These three things start in the same place. The first subarray in arr
is at the beginning of arr
, so it starts where arr
starts. And the first element of arr[0]
is at the beginning of arr[0]
, and it is at the beginning of arr
. Since the three things all start in the same place, it is not surprising that they appear to thace the same address.
Now, let’s look at what you printed. First, when printing a pointer, you ought to convert it to void *
, as in printf("%p\n", (void *) arr);
.
That said, printf(… arr)
prints the address of arr[0]
. Why arr[0]
and not arr
? Because, when used in an expression like this, an array is automatically converted to a pointer to its first element. So arr
is automatically converted to a pointer to arr[0]
, and this is what the printf
prints.
Similarly, printf(… *(arr))
prints the address of arr[0][0]
. This is because, as above, arr
is converted to a pointer to arr[0]
. Then, since it is a pointer to arr[0]
, *(arr)
applies *
to that pointer, and the result is arr[0]
. Since arr[0]
is an array, it is also converted to a pointer to its first element. So the result is a pointer to arr[0][0]
and that is what printf
prints.
So, you are printing the address of arr[0]
and the address of arr[0][0]
. Since they start in the same place, it is not surprising the address is the same.
(It is not actually required that printing the addresses would produce the same string. The C standard allows an implementation to represent addresses in multiple ways. So it is possible that printing two different pointers to the same address could result in different output. That is fairly rare in modern C implementations.)
Except when it is the operand of the sizeof
or the unary &
operator, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T
" is converted ("decays") to an expression of type "pointer to T
", and the value of the expression is the address of the first element of the array.
Given the declaration
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
the memory layout will be
+---+
a: | 1 | a[0][0]
+---+
| 2 | a[0][1]
+---+
| 3 | a[0][2]
+---+
| 4 | a[1][0]
+---+
| 5 | a[1][1]
+---+
| 6 | a[1][2]
+---+
So, one thing to notice - the address of a
will be the same as the address of a[0]
, which will be the same as the address of a[0][0]
. The address of a[1]
will be the same as the address of a[1][0]
.
The expression a
has type "2-element array of 3-element array of int
", so unless it's the operand of &
or sizeof
, the type of the expression will "decay" to "pointer to 3-element array of int
(int (*)[3]
), and its value will be the address of the first element of a
(&a[0]
).
The expression *a
has type "3-element array of int
", so unless it is the operand of &
or sizeof
, the type of the expression will "decay" to "pointer to int
, and the value of expression will be the address of the first element of *a
(&(*a)[0]
, which is equivalent to &a[0][0]
).
As mentioned above, the address of a
is the same as the address of a[0]
, which is the same as the address of a[0][0]
. In fact, all of the following expressions evaluate to the same address: &a
, a
, *a
, a[0]
, &a[0]
, &a[0][0]
, although the types of the expressions are different. See the following table:
Expression Type "Decays" to Value
---------- ---- ----------- -----
a int [2][3] int (*)[3] Address of a[0]
*a int [3] int * Value of a[0]
&a int (*)[2][3] n/a Address of a
a[i] int [3] int * Value of a[i]
*a[i] int n/a Value of a[i][0]
&a[i] int * n/a Address of a[i]
a[i][j] int n/a Value of a[i][j]
&a[i][j] int * n/a Address of a[i][j]
arr without indices is basically a pointer to the zeroeth element of the array, in context of your question there is no difference
arr <==> *arr
that is the reason you are getting the same address, In the next stage lets, we want to access the array elements then one method is trivial arr[i][j]
or you can implement it like this in using pointer *(*(arr + i) + j)
, now the implementation may seem more different from each other but they are both accessing the same address just like in your case, so in this example also there address will be same, and same for all such cases.