之间有什么区别
#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]
?
答案 0 :(得分:6)
不,他们不相同,他们代表不同的类型。参考你的代码,
在第一种情况下,a
是一维数组。因此,a[1]
属于int
类型。
§)要打印该值,%d
没问题。
然而,在第二种情况下,a
是一个二维数组。因此,a[1]
的类型为int [3]
。
§)当作为函数参数传递时,它会衰减到指向第一个元素的指针,基本上是int *
。根据{{1}}格式说明符的要求,您需要%p
打印它(并将指针强制转换为void *
。)
但是,如果您对这两个变量的内存布局感到困扰,可以查看other answer by AnT或another one有关多维数组内存布局的详细信息。
答案 1 :(得分:3)
int a[3][3]
是int a[9]
上的语义糖。原始内存布局相同(即它是9 int
s的连续块),但语言级访问语法不同。当a[3][3]
作为a[i][j]
访问时,编译器将明显的2D索引转换为使用i * 3 + j
公式的1D索引。后一种索引转换方案可以很容易地扩展到任意数量的维度。
答案 2 :(得分:3)
之间有什么区别
int a1[9];
和
int a2[3][3];
(我已更改名称,因此我可以更轻松地讨论声明。)
不同之处在于它们的类型不同。它们都具有相同的底层内存布局,每个内存布局都是连续的内存区域,大小是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*
类型,并生成指向第二行{的初始元素的指针{1}}。要打印指针值,请使用a2
- 这需要类型为%p
的参数,因此您需要强制转换它:
void*
推荐阅读:comp.lang.c FAQ的第6部分。