简体   繁体   English

printf和gcc -O选项更改返回值

[英]printf and gcc -O option change return value

i'm trying to understand how gcc -O option and printf can change return value. 我试图了解gcc -O选项和printf如何更改返回值。

in the code below isTmax is my function that return 1 if the input is the largest int value. 在下面的代码中, 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;
}

it worked perfectly when i compiled it without gcc option. 当我在没有gcc选项的情况下编译它时,它工作得很好。

but with -O option, i got 0 for all integer values. 但是使用-O选项,所有整数值都为0。

so i added printf to check values and then compiled it with -O option. 所以我添加了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;
}

And suddenly it's working again. 突然,它又开始工作了。

i want to know why the return value varies. 我想知道为什么返回值会变化。

As it was pointed out in the comments, this is because of undefined behaviour. 正如评论中指出的那样,这是由于行为不确定。

Modern compilers can (ab)use undefined behaviour to simplify, shorten, and speed up the compiled code without violating any rules. 现代编译器可以(ab)使用未定义的行为来简化,缩短和加速编译的代码,而不会违反任何规则。 I suggest you read that excellent article about the dangers of UB. 我建议您阅读那篇有关UB危害的出色文章

It's hard to know what exactly is going on because optimizer are becoming exceedingly complex, but here's a take on what the compiler might be doing with your function. 很难知道到底发生了什么,因为优化器变得异常复杂,但这是编译器可能会对您的函数进行的处理。

(1) int isTmax(int x)
(2) {
(3)     int temp = x + x + 2;
(4)     int result = !temp & (!!(~x));
(5)     return result;
(6) }

On line 3, you're adding together two signed integers. 在第3行中,您将两个有符号整数加在一起。 If your program only call this function once with 0x7fffffff , the compiler already knows that the code only produces an integer overflow. 如果您的程序仅使用0x7fffffff调用此函数一次,则编译器已经知道该代码仅产生整数溢出。 There's a twist with that code ; 该代码有一个错误之处; since you add 2 to an overflowing operation, the compiler can assume that the value will be positive and greater than two for the sake of what comes next. 由于您将2加到一个溢出的操作中,因此编译器可以假定该值将为正数,并且为了接下来的处理,该值大于2。

On line 4, !temp translate to the boolean constant false since temp is assumed to be a positive value. 在第4行, !temp转换为布尔常量false因为temp被假定为正值。 Next, the and ; 接下来, and since the left value is false (or 0), result always end up being 0. If the result is always zero, the optimizer might as well remove all the variables and operations. 由于左侧的值为false(或0), result总是以0结尾。如果结果始终为零,则优化器可能会删除所有变量和运算。

So essentially, after optimization, your function looks like : 因此从本质上讲,经过优化后,您的函数如下所示:

int isTmax(int x)
{
    return 0;
}

By adding a printf inside the function, you're forcing the optimizer into de-optimizing, so you end up with the same code you get when you don't optimize your program. 通过在printf内部添加一个printf ,您将迫使优化器去优化,因此最终您将得到不优化程序时得到的相同代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM