用-O3编译时的不同评估

ats*_*ich 1 c++ optimization evaluation gcc while-loop

当使用g++ -O3 ..和不使用时,以下代码具有不同的行为-O3

我知道这updateError不会返回任何东西,这可能导致不确定的行为。我不明白的是,error如果使用-O3 if(error > eps)进行编译,则在循环内将其设置为零,并且被评估为false,而在while()语句中仍被评估为true 。。

我还尝试将其更改为do {} while()循环,在这种情况下,它也可以与-O3一起使用...

#include <stdio.h>


using namespace std;


double updateError(){
    printf("updating Error\n");
}

int main(int argc, char *argv[]){

    double eps = 1.e-10;
    double error = 2*eps;
    int iter = 0;

    while(error > eps){
        error = updateError();
        iter++;
        printf("Error on iteration %i: %.20e\n", iter, error);
        if(error > eps) printf("error bigger\n\n");
        else printf("error smaller\n\n");
        if(iter == 5){
            printf("not converged in 5 iterations!!\n");
            break;
        }
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

带有-O3的控制台输出:

updating Error
Error on iteration 1: 0.00000000000000000000e+00
error smaller

updating Error
Error on iteration 2: 0.00000000000000000000e+00
error smaller

updating Error
Error on iteration 3: 0.00000000000000000000e+00
error smaller

updating Error
Error on iteration 4: 0.00000000000000000000e+00
error smaller

updating Error
Error on iteration 5: 0.00000000000000000000e+00
error smaller

not converged in 5 iterations!!
Run Code Online (Sandbox Code Playgroud)

不带-O3的控制台输出:

updating Error
Error on iteration 1: 6.92743341769227318242e-310
error smaller
Run Code Online (Sandbox Code Playgroud)

for*_*818 10

我知道updateError不返回任何东西,这可能导致未定义的行为。

没有“可以”。您的代码具有未定义的行为。期。

在调试时,编译器会做一些额外的工作来增强调试器的使用。这可以像是实际上不必初始化变量时那样。在优化的构建中不会完成这种开销。无论如何,如果您想了解为什么获得结果,那么您应该看一下组装。请注意,UB是UB,因此您无法保证在第二天使用相同的编译器可获得相同的结果。

我不明白的是,如果使用-O3进行编译,则在循环内将错误设置为零,并且if(error> eps)的评估结果为false,而while()语句中的评估结果仍然为true。。

请注意,您编写的代码不会逐行转换为CPU的指令。编译器非常聪明,并且会在视情况规则下应用各种转换。只要可观察到的行为相同,编译器就可以将您的代码转换为与天真的逐行转换完全不同的东西。但是,如果您的代码具有UB,则它不是有效的c ++代码,并且对于一个相同的变量获取不同的输出并不令人感到意外。