c - 使用另一个数组索引一个数组 - gcc 6.3 运行时错误

标签 c gcc language-lawyer

我在 SO 上读到一个关于导致运行时错误(即段错误)的代码的问题。

我尝试使用 ideone.com 调试代码,但得到了一个奇怪的结果。

我已将代码精简为最小版本以重现奇怪的行为。因此代码没有做任何有意义的事情。代码的目的只是为了展示奇怪的行为。

代码示例 1:

#include <stdio.h>

int main() {
    int a[3] = {3, 2, 5};
    int s[3] = {0, 0, 0};
    int r = 0;
    int i;
    for(i = 1; i < 3; i++) {
        while((a[i] < a[s[r]]) && (r >= 0)) 
        {
            r--;
        }
        printf("initialize s[%d] to %d\n", r+1, i);
        ++r;
        s[r] = i;
    }
    printf("%d\n", r);
    return 0;
}

此代码给出运行时错误。

参见 https://ideone.com/IWo6TS#stdin

所以我对代码做了这个小改动。

代码示例 2:

#include <stdio.h>

int main() {
    int a[3] = {3, 2, 5};
    int s[3] = {0, 0, 0};
    int r = 0;
    int i;
    for(i = 1; i < 3; i++) {
        int t = s[r];                          // These 2 lines 
        while((a[i] < a[t]) && (r >= 0))       //
//        while((a[i] < a[s[r]]) && (r >= 0))  // instead of this line
        {
            r--;
        }
        printf("initialize s[%d] to %d\n", r+1, i);
        ++r;
        s[r] = i;
    }
    printf("%d\n", r);
    return 0;
}

现在代码运行良好并产生输出:

initialize s[0] to 1
initialize s[1] to 2
1

参见 https://ideone.com/qt43DL#stdin

使用的编译器是GCC 6.3。

区别仅在于:

.... a[s[r]] .... in example 1

int t = s[r];     in example 2
.... a[t] ....

那么问题是为什么第一个示例失败而第二个示例执行正常?

我在代码中寻找 UB,但找不到任何东西。代码中有UB吗?

这是 GCC 6.3 中的(已知)错误吗?

更新

正如 Scott Hunter 正确指出的那样,两个代码示例做同样的事情。

第一个示例由于 UB 而失败,因为变量 rwhile 的主体内更改为 -1,并且在 while 的下一个条件检查中 它访问 s[-1]。所以 UB 例如 1。

最佳答案

在这两个版本中,rwhile 循环中改变;因此,在第一个版本中与 a[i] 进行比较的 a 元素的索引发生了变化,但在第二个版本中没有变化。

关于c - 使用另一个数组索引一个数组 - gcc 6.3 运行时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46103000/

相关文章:

c - 什么时候需要 F_GETFL fcntl 命令的参数?

c++ - 为什么 C/C++ 中允许单独使用分号?

c++ - 抽象基类中私有(private)虚函数的可见性

python - 使用 swig 将 c++ 编译为 python

c - 将两个无符号数的减法存储为有符号数的语义

java - #define 在 java/android studio 中使用

c - "streams"在C中被称为FILE的历史原因是什么

c - OpenSSL 上的 AES CTR 256 加密操作模式

c - 构建 mlt 时,Cygwin 中对 WinMain 的 undefined reference

c - 在 C 中,什么时候支持条件 "test ? : alt"形式(空的 true 大小写)?