即使使用-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
为什么会这样?在两个代码中,[1] [2] [100]无效。编译器如何检测到这仍然是代码2而不是代码1。
特别是当每个编译器将所有多维数组展平为相应的单维数组时,编译器如何有选择地识别代码中的这个缺陷。
将会感激地接受对正确解释所在的某些书籍或文章的解释或提及:)
答案 0 :(得分:4)
首先,在运行时或编译时不检查数组边界。小心那里。
其次,你的第二种情况会产生错误,因为你的数组维度不匹配 - 你在2D数组上使用了三个下标运算符([]
)。仅仅因为数组恰好在内存中布局,因为数组数组并不意味着变量的实际类型发生了变化。
数组下标在C标准部分 6.5.2.1数组下标中有所描述。
答案 1 :(得分:4)
区别在于类型。 C没有边界检查,但它确实进行(静态)类型检查。第一个示例中的a类型为int[][][]
,但第二个示例中的类型为int[][]
。
您所指的“扁平化”发生在代码生成中,(在概念上,至少)在类型检查之后。
答案 2 :(得分:2)
鉴于
int a[2][3];
编译器将确定a[1][2]
的类型为int
。因此,访问元素[100]
相当于:
int x;
x[100] = 4;
这会给你关于下标值的相同错误。