注意&arr是完整的 3 维 char 数组的地址,而arr指向第一个元素是 2 维 char 数组。如下图所示:
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]
类型&arr是char(*)[5][7][6]char 3D-array 的地址[5][7][6]。&arr和之间的价值差异&arr + 1是5 * 7 * 6 * sizeof(char)= 210。
因为 的大小char[5][7][6]是5 * 7 * 6 * sizeof(char)。
在您的代码&arr中指向 3-D 数组和&arry + 1下一个 3-D 数组(在我们的代码中不存在)。
在codepade检查此工作代码:
int main()
{
char arr[5][7][6];
printf(" &arr : %p", &arr);
printf(" &arr+1: %p", &arr + 1);
return 0;
}
输出:
&arr : 0xbf5dd7de
&arr+1: 0xbf5dd8b0
(&arr + 1) - (&arr)= 0xbf5dd8b0 - 0xbf5dd7de= 0xd2=之间的区别210。
在您的第二个 printf 中:
printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
您将 type 的地址类型转换char(*)[5][7][6]为 plain (char*),并且因为 sizeofchar[5][7][6]是210两个地址都是 210 远。(记住sizeof(char) == 1)。这就是输出的原因:210
现在正如我在第一个语句中所说,arr是第一个元素的地址,它是一个二维字符数组。类型arr是char(*)[7][6]。现在有一个元素(大小为 的二维数组6 * 7 * sizeof(char) = 42)。
(注意:您可以将 3-D 数组视为一维数组,其中每个元素都是一个二维数组)。
在您的第三个 printf 中:
printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
您将类型转换为无符号值(但不是地址/指针类型)。arr + 1和之间的区别arr是42 * sizeof(char)= 42(即等于 的大小char[7][6])。所以 printf 语句输出:42.
注意: 您应该阅读sizeof (int) == sizeof (void*)? ,因为您正在将地址类型转换为值。并且这种转换没有完全定义。(我的解释是你的输出和我给出的输出)。
如需进一步说明,请在codepade上查看以下工作代码:
int main()
{
char arr[5][7][6];
printf(" arr : %p\n", arr);
printf(" arr+1: %p", arr + 1);
return 0;
}
输出是:
arr : 0xbf48367e
arr+1: 0xbf4836a8
(arr + 1) - (arr)取= 0xbf4836a8- 0xbf48367e= 0x2a=之间的差异42。
最后打印:
printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
&arr+1只需取和&arr=之间的差异210(类似于第二个 printf),因为p它是指向 3-D 字符数组 (= &arr) 的指针。而且您正在将其类型转换为值类型(不是指针类型)。
另外,(只是为了理解目的而添加,我想读者会发现它有帮助),
arr让我们了解 sizeof 运算符和使用运算符之间的另一个区别,&arr这将有助于您更深入地理解概念。对于第一次阅读:sizeof操作员
将sizeof运算符应用于数组标识符时,结果是整个数组的大小,而不是数组标识符所表示的指针的大小。
在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;
}
它的输出:
Sizeof(&arr) : 4 and value &arr: 0xbf4d9eda
Sizeof(arr) : 210 and value arr : 0xbf4d9eda
Sizeof(arr[0]): 42 and value a[0]: 0xbf4d9eda
正如我在图表中所示,arr指向二维数组的第一个元素。所以因为arr= (arr + 0)。现在使用*取消引用运算符 at(arr + 0)给出地址 so 的值*(arr + 0) = arr[0]。
- 注意
sizeof(arr[0])给出 42= 7 * 6 * sizeof(char)。这在概念上证明了一个 3 维数组,但值得注意的是 2 维数组的数组。
因为上面在我的回答中很多时候我都写过:“size of char[5][7][6]is 5 * 7 * 6 * sizeof(char)。” 所以我在@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;
}
输出:
Char : 1
Char[5] : 6
Char[5][7] : 42
Char[5][7][6]: 210