main()
{
int a[2][3][2]={{1,2},{9,8},{3,7}},{{2,2},{1,4},{5,4}};
printf("%d %d %d",a[1]-a[0],a[1][0]-a[0][0],a[1][0][0]-a[0][0][0]);
}
书中给出的输出是3 6 1.我不确定三维阵列的工作情况。有人可以向我解释上述代码的整个过程吗?
答案 0 :(得分:2)
如图所示,数组初始化为:
int a[2][3][2] = { {{1,2},{9,8},{3,7}}, {{2,2},{1,4},{5,4}} };
(注意与问题中的代码相比,必要的额外一对括号)在内存中看起来像这样:
| a |
| a[0] | a[1] |
| a[0][0] | a[0][1] | a[0][2] | a[1][0] | a[1][1] | a[1][2] |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 9 | 8 | 3 | 7 | 2 | 2 | 1 | 4 | 5 | 4 |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^ ^ ^
0x1000 0x1010 0x1020 0x1030
起始地址是假设的,方便的而不是现实的;我假设sizeof(int) == 4
,这是最常见的值,但不是标准保证。在下面的讨论中,地址范围包括起始地址和排除结束地址。
此图表显示的是12个数字在内存中线性排列,如图所示。因此,整个数组a
的大小为48字节,从地址0x1000到0x1030。子阵列a[0]
从地址0x1000延伸到0x1018;子阵列a[1]
从0x1018扩展到0x1030。子阵列a[0][0]
从0x1000扩展到0x1008; a[1][0]
从0x1018到0x101C;等等。
现在让我们看看printf()
声明:
printf("%d %d %d", a[1]-a[0], a[1][0]-a[0][0], a[1][0][0]-a[0][0][0]);
我们可以观察(我的编译器确实按照我的预期观察到),前两个值实际上是ptrdiff_t
类型,因此正确的格式说明符是%td
,而不是{{ 1}}(虽然在32位平台上,%d
没问题,在64位平台上,%d
可以,但要在两者上都正确,你需要使用{ {1}})。如果输出以换行符结束也会更好。
很容易同意%ld
的值为2,%td
的值为1,因此打印的第三个数字应为1,实际上这就是输出。
向后工作,a[1][0][0]
是一个数组(由两个a[0][0][0]
个元素组成,因此大小为8个字节)从地址0x1018开始;同样,a[1][0]
是一个从地址0x1000开始的数组。但是,由于数组的“衰减”,这些值等于int
(因此a[0][0]
等于int *
或值1),因此原始差异以字节为单位( 0x18 = 24)由指向(*a[0][0]
或4)的对象的大小缩放,得到答案6.
同样,a[0[0][0]
是一个数组(int
类型),a[1]
也是如此。区别是0x18 = 24字节,但这次,int [3][2]
是一个指向2 a[0]
数组的指针,大小为8,因此答案是3。
因此,正如预期的那样,程序的正确输出是:
*a[1]
此外,虽然地址会有所不同,但如果int
或3 6 1
(或实际上是任何其他尺寸,那么计算将是准确的,尽管这些是现代通用的主要合理候选者硬件; DSP硬件可能有sizeof(int) == 2
- 因此sizeof(int) == 8
- 和sizeof(char) == sizeof(int)
甚至可能sizeof(int) == 1
}。
答案 1 :(得分:0)
数组可以是任何其他类型,包括其他数组。所以你拥有的是一个包含两个整数的三个数组的两个数组的数组。