【问题标题】:how arrays are treated by gcc [ question related to C programing ]gcc 如何处理数组 [与 C 编程相关的问题]
【发布时间】:2010-12-02 05:05:06
【问题描述】:

即使使用 -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] 都是无效的。编译器仍然如何检测到这是 code2 而不是 code1。

特别是当每个编译器都将所有多维数组扁平化为对应的一维数组时,编译器如何选择性地意识到代码中的这个缺陷。

如果有正确解释的书籍或文章的解释或提及,我们将不胜感激:)

【问题讨论】:

    标签: c arrays pointers gcc compiler-construction


    【解决方案1】:

    区别在于类型。 C 不进行边界检查,但确实进行(静态)类型检查。第一个示例中 a 的类型是 int[][][],但第二个示例中的类型是 int[][]

    您所指的“扁平化”发生在代码生成中,即(至少在概念上)类型检查之后。

    【讨论】:

    • 这是因为 int [][] 实际上是 int** 而 int [][][] 是 int*** 吗?
    • @SK int*int[] 略有不同。前者意味着静态分配(数据段等),而后者意味着动态分配(堆)。
    • 没有。这是因为你可以用 int 为 int[] 下标,但不能用 int 为 int 下标。如果用 int 为 int[][][] 下标,则会得到 int[][]。如果你用一个 int 下标,你会得到一个 int[]。如果你用一个 int 下标,你会得到一个 int。如果你用 int 下标,你会得到一个类型错误。
    • 顺便说一句,我一直说“with an int”的原因是因为您实际上可以用数组为 int 下标。但是,没有真正的理由这样做,所以最好不要考虑它......;-)
    【解决方案2】:

    首先,在运行时或编译时不检查数组边界。在外面小心点。

    其次,您的第二种情况会出现错误,因为您的数组维度不匹配 - 您在二维数组上使用了三个下标运算符 ([])。仅仅因为数组恰好作为数组数组布局在内存中并不意味着变量会发生任何实际的类型更改。

    数组下标在 C 标准部分 6.5.2.1 数组下标中进行了描述。

    【讨论】:

    • 如果所有数组都被编译器展平,它如何区分 2D 或 3D 数组。
    • @S..K,没有特殊情况。您可以拥有任何类型的数组。 “3D”数组只是“2D”数组等的数组。所有索引都基于指针算法,它考虑了对象的大小(同样,它可能是一个数组)。
    • 编译器必须知道数组的形状。必须声明除最后一个之外的所有尺寸。前任。 arr[5][6][]。这对于解释数组是必要且足够的。
    • 数组的内部实现细节与变量的类型无关。您试图将 2D 数组视为 3D 数组,但这是行不通的。你可以做一些时髦的类型转换来破解它,但绝对不推荐这样做。正如您所注意到的,编译器并不关心您访问数组之外​​的内存,但它确实关心类型,这就是示例 2 中的问题所在。
    【解决方案3】:

    给定

    int a[2][3];
    

    编译器将确定a[1][2] 的类型为int。因此,访问元素[100] this 等价于:

    int x;
    x[100] = 4;
    

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

    【讨论】:

      猜你喜欢
      • 2023-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-13
      • 2011-09-16
      • 1970-01-01
      • 1970-01-01
      • 2017-12-24
      相关资源
      最近更新 更多