使用 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
任何的想法?