使用 GCC6 和下面的代码片段,这个测试
if (i > 31 || i < 0) {
为false,并执行此 printf
printf("i > 31 || i < 0 is FALSE, where i=%d", i);
并产生这个非常奇怪的输出(GCC6):
我 > 31 || i < 0 是FALSE,其中i=32 /* GCC6 的奇怪结果!!!*/
而使用 GCC4 我得到:
我 > 31 || i < 0 为真,其中i=32 /* 结果与 GCC4 一致 */
看起来完全没问题。
怎么会这样??
static int check_params(... input parameters ...) {
/* Note that value can be 0 (zero) */
uint32_t value = ....
int i;
i = __builtin_ctz(value);
if (i > 31 || i < 0) {
printf("i > 31 || i < 0 is true, where i=%d", i);
/* No 1 found */
return 0;
} else {
printf("i > 31 || i < 0 is FALSE, where i=%d", i);
}
return i;
}
根据关于 GCC 内置函数的文档,必须避免调用 __builtin_ctz(0) :
内置函数:int __builtin_ctz (unsigned int x) 返回 x 中从最低有效位位置开始的尾随 0 位的数量。如果 x 为 0,则结果为 undefined。
所以很明显,编码错误的解决方案是在调用 __builtin_ctz(value) 之前简单地检查值。这是清楚明白的。
我可以停在那里并转向其他主题......但是,我仍然不明白我怎么可能(使用损坏的代码)获得以下输出:
我 > 31 || i < 0 是FALSE,其中i=32 /* GCC6 的奇怪结果!!!*/
奇怪的 GCC6 优化还是什么?
以防万一它很重要:
Cross-compiler: arm-linux-gcc
Architecture: -march=armv7-a
任何想法?
除非未定义的行为,__builtin_ctz
将始终返回 0 到 31 之间的数字,GCC 知道这一点。因此,检查i > 31 || i < 0
将始终为假(再次禁止未定义的行为)并且可以优化掉。
如果您查看生成的程序集,您会看到条件根本没有出现在代码中(then-case 也没有)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句