两者有什么区别?
#include <stdio.h>
int a[9];
int
main()
{
printf("%d\n", a[1]);
}和
#include <stdio.h>
int a[3][3];
int
main()
{
printf("%d\n", a[1]);
}我认为这两者都会导致在.bss部分放置相同的36字节内存缓冲区,有什么区别呢?或者是a[3][3]语法糖在a[9] - a[3*3]上
发布于 2016-09-16 17:54:40
int a[3][3]是int a[9]的一种语义糖。原始内存布局相同(即它是一个9ints的连续块),但是语言级别的访问语法不同。当以a[i][j]的形式访问a[i][j]时,编译器使用i * 3 + j公式将显式2D索引转换为一维索引。后一种索引转换方案很容易扩展到任意维数。
发布于 2016-09-16 17:36:28
发布于 2016-09-16 18:21:09
两者有什么区别? int a19; 和 int a23;
(我已经更改了名称,以便更容易地讨论声明。)
不同之处在于它们是不同类型的。它们都有相同的底层内存布局,每一个内存的连续区域都是int大小的9倍。但是a1是一个由9个int对象组成的数组,而a2是一个由3个对象组成的数组,每个对象都是一个由3个int对象组成的数组。它是一个多维数组,在C中它恰恰是一个数组,仅此而已。
不同之处不只是句法上的糖。对于某些操作,您可能会得到相同的生成代码,例如a1[1]和a2[0][1]。但是,例如,a1[3]引用数组a1的第4个元素,而a2[0][3] (尽管您可能认为它引用的是相同的东西)实际上具有未定义的行为。(编译器允许但不需要执行运行时数组绑定检查,并且允许假定数组引用不会超过索引数组对象的末尾。)
printf("%d\n", a2[1]);正如其他人所提到的,这是一种未定义的行为。a2[1]是int[3]类型的数组对象。在大多数上下文中,数组类型的表达式被转换为指针类型的表达式,因此a2[1]以int*类型结束,并生成指向a2第二行的初始元素的指针。要打印指针值,请使用%p --这需要一个void*类型的参数,因此您需要转换它:
printf("%p\n", a2[1]);推荐阅读:常见问题解答第6节。
https://stackoverflow.com/questions/39537204
复制相似问题