即使使用 -Wall 选项,它也会在 gcc 中编译,没有错误或警告 这意味着在运行时检查数组边界,因此编译器无法检测到错误
#include<stdio.h>
int main()
{
int a[2][3][4];
a[1][2][100] = 4 ;
return 0;
}
但是,
#include<stdio.h>
int main()
{
int a[2][3];
a[1][2][100] = 4 ;
return 0;
}
这会在编译时生成错误:
$ gcc sample.c -Wall
sample.c: In function ‘main’:
sample.c:7: error: subscripted value is neither array nor pointer
为什么会这样?在这两个代码中,a[1][2][100] 是无效的。编译器仍然如何检测这是代码2而不是代码1。
特别是当每个编译器都将所有多维数组平铺为相应的单维数组时,那么编译器如何选择性地意识到代码中的这个缺陷。
对一些有正确解释的书籍或文章的解释或提及将不胜感激:)
区别在于类型。 C 不进行边界检查,但进行(静态)类型检查。第一个示例中 a 的类型是
int[][][]
,但第二个示例中的类型是 int[][]
。
您所指的“扁平化”发生在代码生成中,(至少从概念上来说)是在类型检查之后。
首先,在运行时或编译时不会检查数组边界。 出门要小心。
其次,第二种情况会出现错误,因为数组维度不匹配 - 您在二维数组上使用了三个下标运算符(
[]
)。 仅仅因为数组恰好作为数组的数组布置在内存中并不意味着变量发生任何实际类型更改。
数组下标在 C 标准部分6.5.2.1 数组下标中描述。
鉴于
int a[2][3];
编译器将确定
a[1][2]
的类型为 int
。因此,访问此元素[100]
相当于:
int x;
x[100] = 4;
这会给你带来关于下标值的相同错误。