gcc如何处理数组[与C编程相关的问题]

时间:2010-12-02 05:05:07

标签: c arrays pointers gcc compiler-construction

即使使用-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。

特别是当每个编译器将所有多维数组展平为相应的单维数组时,编译器如何有选择地识别代码中的这个缺陷。

将会感激地接受对正确解释所在的某些书籍或文章的解释或提及:)

3 个答案:

答案 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;

这会给你关于下标值的相同错误。