Note &arr
is complete 3-dimensional char array's address, whereas arr
points to first element that is 2-dimensional char array. Something like below in diagram:
0xbf8ce2c6
+------------------+ ◄-- arr = 0xbf8ce2c6
| 0xbf8ce2f0 |
| +------------------+ ◄-- arr + 1 = 0xbf8ce2f0
| | 0xbf8ce31a | |
| | +------------------+ ◄-- arr + 2 = 0xbf8ce31a
| | 0xbf8ce344 | | |
| | | +------------------+ ◄-- arr + 3 = 0xbf8ce344
| | 0xbf8ce36e | | | |
| | | | +------------------+ ◄-- arr + 4 = 0xbf8ce36e
| | | | | | | | | |
+---|---|---|--|---+ | | | | Each are 7*6, 2-Dimensional
| | | | | | | | Consists Of 42 bytes
+---|---|--|-------+ | | |
| | | | | |
+---|--|-----------+ | |
| | | |
+--|---------------+ |
| |
+------------------+
The diagram show:
1. How a 3-dimensional can be interpreted as series of 2-dimensional arrays
2. Here (arr + i) points to a 2-D array
3. Notice difference between: (arr + i + 1) - (arr + i) = 0x2a = 42, where i = [0, 4]
Type of &arr
is char(*)[5][7][6]
that is address of char 3D-array of dimension [5][7][6]
.
Value-wise difference between &arr
and &arr + 1
is 5 * 7 * 6 * sizeof(char)
= 210
.
Because size of char[5][7][6]
is 5 * 7 * 6 * sizeof(char)
.
In your code &arr
points to 3-D array and &arry + 1
next 3-D array (that doesn't exist in our code).
Check this working code at codepade:
int main()
{
char arr[5][7][6];
printf(" &arr : %p", &arr);
printf(" &arr+1: %p", &arr + 1);
return 0;
}
Output:
&arr : 0xbf5dd7de
&arr+1: 0xbf5dd8b0
Difference between (&arr + 1) - (&arr)
= 0xbf5dd8b0 - 0xbf5dd7de
= 0xd2
= 210
.
In your second printf:
printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
You typecasts addresses of type char(*)[5][7][6]
to plain (char*)
, and because sizeof char[5][7][6]
is 210
both addresses are 210 far. (remember sizeof(char) == 1
). This is the reason outputs: 210
Now as I said in first statement, arr
is address of first element that is a two dimensional array of chars. Type of arr
is char(*)[7][6]
. Now one element (two-dimensional array of size is 6 * 7 * sizeof(char) = 42
).
(Note: you can think a 3-D array as one-d array where each element is a 2-d array).
In your third printf:
printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
You typecasts to unsigned value (but not to an address/pointer type). The difference between arr + 1
and arr
is 42 * sizeof(char)
= 42
(that is equals to size of char[7][6]
). So the printf statement outputs: 42
.
Note: You should read sizeof (int) == sizeof (void*)?, because you are typecasting address to value. and this conversion is not fully defined. (my explanation is wrt your output and the output I have given).
For further clarification check below working code at codepade:
int main()
{
char arr[5][7][6];
printf(" arr : %p\n", arr);
printf(" arr+1: %p", arr + 1);
return 0;
}
Output is:
arr : 0xbf48367e
arr+1: 0xbf4836a8
Take difference between (arr + 1) - (arr)
= 0xbf4836a8
- 0xbf48367e
= 0x2a
= 42
.
Last printf:
printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
Just take difference between &arr+1
and &arr
= 210
(similar to second printf) because p
is pointer to 3-D char array (=&arr
). And you are typecasting it to value type(not pointer type).
Additionally, (Just adding for understanding purpose, I guess reader will find it helpful),
Lets we learn one more difference between arr
and &arr
using sizeof operator that will help your to understand concept more deeper. For this first read: sizeof
Operator
When you apply the sizeof
operator to an array identifier, the result is the size of the entire array rather than
the size of the pointer represented by the array identifier.
Check this working code at codepade:
int main()
{
char arr[5][7][6];
printf(" Sizeof(&arr) : %lu and value &arr: %p\n", sizeof(&arr), &arr);
printf(" Sizeof(arr) : %lu and value arr : %p\n", sizeof(arr), arr);
printf(" Sizeof(arr[0]): %lu and value a[0]: %p\n",sizeof(arr[0]), arr[0]);
return 0;
}
Its output:
Sizeof(&arr) : 4 and value &arr: 0xbf4d9eda
Sizeof(arr) : 210 and value arr : 0xbf4d9eda
Sizeof(arr[0]): 42 and value a[0]: 0xbf4d9eda
Here &arr
is just an address, and in the system address is of four-bytes and this is address of complete 3-dimensional char array.
arr
is name of 3-dimensional array, and sizeof
operator gives total size of array that is 210 = 5 * 7 * 6 * sizeof(char)
.
As I shown in my diagram arr
points to first elements that is an 2-dimensional array. So because arr
= (arr + 0)
. Now using *
Dereference operator at (arr + 0)
gives value at address so *(arr + 0) = arr[0]
.
- Notice
sizeof(arr[0])
gives 42
= 7 * 6 * sizeof(char)
. And this proofs conceptually a 3-dimensional array is noting but array of 2-dimensional array.
Because above in my answer at many time I written like: "size of char[5][7][6]
is 5 * 7 * 6 * sizeof(char)
." so I am adding an interesting code below @codepade:
int main(){
printf(" Char : %lu \n", sizeof(char));
printf(" Char[5] : %lu \n", sizeof(char[6]));
printf(" Char[5][7] : %lu \n", sizeof(char[7][6]));
printf(" Char[5][7][6]: %lu \n", sizeof(char[5][7][6]));
return 1;
}
Output:
Char : 1
Char[5] : 6
Char[5][7] : 42
Char[5][7][6]: 210