[英]printf and gcc -O option change return value
我试图了解gcc -O选项和printf如何更改返回值。
在下面的代码中, isTmax
是我的函数,如果输入是最大的int值,则返回1。
int isTmax(int x);
int main(void)
{
printf("%d\n", isTmax(0x7fffffff));
}
int isTmax(int x)
{
int temp = x + x + 2;
int result = !temp & (!!(~x));
return result;
}
当我在没有gcc选项的情况下编译它时,它工作得很好。
但是使用-O选项,所有整数值都为0。
所以我添加了printf来检查值,然后使用-O选项对其进行编译。
int isTmax(int x)
{
int temp = x + x + 2;
int result = !temp & (!!(~x));
printf("x : %x, temp : %x, !temp : %x\n", x, temp , !temp);
return result;
}
突然,它又开始工作了。
我想知道为什么返回值会变化。
正如评论中指出的那样,这是由于行为不确定。
现代编译器可以(ab)使用未定义的行为来简化,缩短和加速编译的代码,而不会违反任何规则。 我建议您阅读那篇有关UB危害的出色文章 。
很难知道到底发生了什么,因为优化器变得异常复杂,但这是编译器可能会对您的函数进行的处理。
(1) int isTmax(int x)
(2) {
(3) int temp = x + x + 2;
(4) int result = !temp & (!!(~x));
(5) return result;
(6) }
在第3行中,您将两个有符号整数加在一起。 如果您的程序仅使用0x7fffffff
调用此函数一次,则编译器已经知道该代码仅产生整数溢出。 该代码有一个错误之处; 由于您将2加到一个溢出的操作中,因此编译器可以假定该值将为正数,并且为了接下来的处理,该值大于2。
在第4行, !temp
转换为布尔常量false
因为temp被假定为正值。 接下来, and
; 由于左侧的值为false(或0), result
总是以0结尾。如果结果始终为零,则优化器可能会删除所有变量和运算。
因此从本质上讲,经过优化后,您的函数如下所示:
int isTmax(int x)
{
return 0;
}
通过在printf
内部添加一个printf
,您将迫使优化器去优化,因此最终您将得到不优化程序时得到的相同代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.