Reputation: 73
Consider the c code below.
#include <stdio.h>
int main(){
unsigned int x[4][3] = {{1, 2, 3}, {4, 5, 6},
{7, 8, 9}, {10, 11, 12}};
printf("%u, %u, %u", x+3, *(x+3), *(x+2)+3);
printf("\n%u, %u, %u", x,&x,*x);
return 0;
}
Now each of the printf statement prints the same values as mentioned below.
6356724, 6356724, 6356724
6356688, 6356688, 6356688
Process returned 0 (0x0) execution time : 0.128 s
Press any key to continue.
I wanted to know how is the outcome same in each printf statements.
This is my understanding of memory layout of 2-D array.
Now I believe x+3 refers to base address of( x + 3 * size require for pointer arithmetic ) = 24 and *(x +3 ) = *(24) = 2036 but its not the case the first printf statement prints 2036, 2036 2036 . I wanted to visually understand how exactly 2-D array is organized.
Upvotes: 2
Views: 648
Reputation: 115
I'll try to explain from a layman's point of view.
Let us assume the base address is 3000, and assume that integer takes 4 bytes.
Considering your 2-D array, this is how WE visualise a 2-D array in the memory :
0 1 2
--------------------------------------------------
0 | 1 | 2 | 3 |
| 3000/3001/3002/3003| 3004/05/06/07 | 3008/09/10/11|
|___________________ |________________|______________|
1 | 4 | 5 | 6 |
| 3012 | 3016 | 3020 |
|____________________|________________|______________|
2 | 7 | 8 | 9 |
| 3024 | 3028 | 3032 |
|____________________|________________|______________|
3 | 10 | 11 | 12 |
| 3036 | 3040 | 3044 |
| | | |
------------------------------------------------------
Now, you should know how a 2-D array is actually stored just like a 1-D array in the memory:
index 0 1 2 3 4 5 6 7 8 9 10 11
---------------------------------------------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| | | | | | | | | | | | |
add. |3000__|_3004_|_3008_|_3012_|_3016_|_3020|3024__|_3028_|3032__|_3036_|_3040|3044_ |
Now, your code says:
printf("%u, %u, %u", x+3, *(x+3), *(x+2)+3);
(i) x+3
Here x is your base address, which is 3000(assumed), and +3 means the 3rd row. Since there is nothing after that,i.e, x+3, we will find out the address of the first element of the 3rd row.
=3000+36=3036
(refer the 2D array visualisation that WE see, the first one)
(ii) *(x+3)
This is the same as x+3, i.e, we have to find the address of the first element of the third row. I say the first element because if something was mentioned after *(x+3)+'something', then we would be concerned about finding it.
=3000+36=3036.
(refer the 2D array visualisation that WE see, the first one)
(iii) *(x+2)+3
Just for understanding, let us break this into two parts.
First, *(x+2): as we have seen in the above two parts, *(x+2) says that "I have started from the base address, now give me the address of the first element of the 2nd row. So, we reach element with value 7 and address 3024. (refer the 2D array visualisation that WE see, the first one)
Second, +3 as in *(x+2)+3 means that since we have reached element with value 7 and address 3024, now see/move to the 3rd element after the element with value 7 and address 3024 (where we are right now). So, we move past/see-through elements with values 8 and 9, with addresses 3028 and 3032 respectively, and reach/land on the element with value 10 and address
=3000+36=3036
(refer the 2D array visualisation that WE see, the first one)
For your second code:
printf("\n%u, %u, %u", x,&x,*x);
I go with @n. 'pronouns' m. answer.
Upvotes: 2
Reputation: 119877
Whenever an array is mentioned, it decays to a pointer to its first element (except in a few cases that are not interesting right now).
Why x
, &x
and *x
are all printed the same? That's because the array itself, its first element, (and if it's a 2D array, the first element of its first element, which is by itself a 1D array) all have the same address.
So:
&x
is the pointer to the array x
is the array itself, which decays to the pointer of its first element*x
is the first element of the array, which is itself an array (1, 2, 3}
, so it decays to the pointer of its first elementAll these pointers have different types, but point to the same address.
The same thing happens with x+3
and *(x+3)
. First, x
decays to a pointer, then pointer arithmetic is performed. Say y = x + 3
, so y
and *y
point to the same address just as x
and *x` do (see above).
What about *(x+2)+3
? Well, *(x + 2)
is itself is an array of 3 elements. So *(x+2)+3
points to one element past the end of the *(x + 2)
array. This non-existing element has an address nevertheless, and it is the same as the address of the first element of the *(x + 3)
array --- because *(x + 2)
and *(x + 3)
are next to each other in the x
array.
Upvotes: 5