【问题标题】:Array Values in C loops( clang vs gcc)C循环中的数组值(clang vs gcc)
【发布时间】:2016-12-06 13:30:10
【问题描述】:

我试图在 c 的 for 循环中使用数组初始化。

这是我尝试过的程序:

#include<stdio.h>
int main(){
for(int i=0;i<3;i++){
    for(int j=0;j<3;j++){
        int br[10]={0};
        printf("%d\n", br[-1]);
    }
 }

 return 0;
}

这段代码用gcc编译的结果是:

0 1 2 0 1 2 0 1 2

同一个程序,用clang编译,结果是:

0 0 0 0 0 0 0 0 0

如果我通过在第二个循环开始之前进行数组初始化来稍微调整程序:

#include<stdio.h>


int main(){
 for(int i=0;i<3;i++){
    int ar[10]={0};
    for(int j=0;j<3;j++){
        int br[10]={0};
        printf("%d\n", br[-1]);
    }
 }

 return 0;
}

gcc 和 clang 的输出都为 0 0 0 0 0 0 0 0 0

谁能解释这里到底发生了什么,当我尝试访问负索引时,为什么这些结果会显示在这两个不同的编译器(gcc 和 clang)中,为什么在第二个循环之前另一个数组初始化会改变一切。

【问题讨论】:

  • br[-1]Undefined Behavior.... 就是这样
  • 我不这么认为。我认为这与内存分配有关。
  • 不,是UB,纯粹而简单。编译器保留吃掉你的猫的权利。
  • 我会说这是未指定或实现定义的行为,因为只有值未定义但 br[-1] 是!
  • @izlin:你怎么知道 br[-1] 被定义了?如果您正在考虑“堆栈”,请注意堆栈是一个实现概念而不是语言概念。

标签: c gcc clang llvm-clang


【解决方案1】:

br[-1] 的行为是未定义

C 标准没有定义尝试访问数组边界 之外的元素的行为。 (有趣的是,这主要是为什么 C 被许多人认为是一种“不安全”的语言。)您总是可以检查生成的汇编程序以全面分析编译器产生的内容。

【讨论】:

    【解决方案2】:

    Here is an example of using negative array idexes.

    如果您使用 br[-1],您会在数组之前打印元素:

    some stuff | your array | more stuff
     X X X X X | 0 0 0 0 ...| X X X X
             ^ this element will be printed
    

    因此,在一种情况下,您可能会得到 i 或 j 的值,但数组前面的数字可能会随着不同的编译器或编译器选项而改变。

    @芭丝谢芭 在我的链接中,最重要的答案说行为是在 C99 §6.5.2.1/2 中定义的,但您不知道哪个变量位于您的数组前面。

    下标运算符[]的定义是E1[E2]等同于(*((E1)+(E2)))。

    【讨论】:

      猜你喜欢
      • 2013-08-21
      • 1970-01-01
      • 1970-01-01
      • 2018-03-29
      • 2016-12-13
      • 2011-08-30
      • 1970-01-01
      • 2018-02-08
      • 2015-05-13
      相关资源
      最近更新 更多