【问题标题】:'while' statement works differently when using optimization (GCC)使用优化 (GCC) 时,'while' 语句的工作方式不同
【发布时间】:2014-12-15 15:51:28
【问题描述】:

这样一段代码我有问题:

uint8_t var1, var2, var3, var4, var5[];
...
while ( ((var1 & var2) != var3) && (var4 < (sizeof(var5)/sizeof(var5[0]))) ){
... do something
}

我在 GCC 中有一个 -O3(最优化)选项。在这种情况下,代码以某种奇怪的不可预测的方式工作。 当我有一个-O0(无优化)选项时,它工作得很好。

如何强制带有-O3 选项的编译器不只优化while(...) 行? 我尝试在内部使用volatile,但没有成功。我想打开-O3 选项,但要让代码正常工作。

编辑:

好的,这是完整的示例代码。可能是我的错,但我不明白问题出在哪里。

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>


struct st{
    uint8_t     var1;
    uint8_t     var2;
};


int main(void) {

    uint8_t         k = 0;

    uint8_t         arr1[4] = {0, 0b11000000, 0b10000000, 0};

    const struct st arr2[] = {

            {0b11000000, 0b11000000},
            {0b10000000, 0b11000000}
    };

    printf("size of arr2: %d \n\n",sizeof(arr2)/sizeof(arr2[0]));

    while ( ((arr1[k] & arr2[k].var2) != arr2[k].var1) && (k < (sizeof(arr2)/sizeof(arr2[0]))) ){
        printf("k: %d \n",k);
        k++;
    }



    return 0;
}

用 -O0 和 -O3 运行它,你会看到区别。

EDIT2: -O0 的输出:

size of arr2: 2

k: 0
K: 1

使用-O3:

size of arr2: 2

k: 0
K: 1
k: 2
K: 3

我希望 k 在任何 -O 选项下不应超过 2。

【问题讨论】:

  • 我更好奇为什么-O3 会破坏你的代码。你在使用未定义的行为吗?
  • 不可预测听起来像是未定义的行为,但我们需要查看更多代码,产生online example 行为的最少代码量是理想的。
  • 我想问题出在 ... 或 ... 做某事。
  • 奥卡姆剃刀。不要责怪编译器。请注意,sizeof 是编译时评估的。
  • 尝试交换谓词的顺序?看起来你正在离开数组的末端。

标签: c gcc optimization


【解决方案1】:

由于 cmets 部分的噪音太大:

正如@Kevin 所说,您的while (B &amp;&amp; A) 应该是while (A &amp;&amp; B),因为A 正在检查边界并且语句从左到右执行直到错误。因此,B 将在数组索引 k 在达到 A 评估为 false 并停止循环之前超出范围时调用未定义的行为。

【讨论】:

  • 非常感谢!现在它起作用了。但是我真的不明白为什么(1 && 0)不等于(0 && 1)?
  • @cyclone125 因为short-circuit evaluation
  • @cyclone125 最终结果是它们都评估为假,但是正如我在回答中所说,它从左到右进行评估并一直持续到一个陈述为假或者它在结尾陈述,因此一切都是真实的。 1 &amp;&amp; 0true &amp;&amp; false(STOP)0 &amp;&amp; 1 变成 false(STOP) 其余的被忽略。
猜你喜欢
  • 1970-01-01
  • 2017-06-16
  • 2014-01-13
  • 2012-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-27
  • 2016-11-14
相关资源
最近更新 更多