簡體   English   中英

用-O3編譯時的不同評估

[英]Different evaluation when compiling with -O3

當使用g++ -O3 ..且不使用-O3編譯時,以下代碼具有不同的行為。

我知道updateError不返回任何東西,這可能導致未定義的行為。 我不明白的是,如果使用-O3進行編譯,則該error在循環內設置為零,並且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;
}

帶有-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!!

不帶-O3的控制台輸出:

updating Error
Error on iteration 1: 6.92743341769227318242e-310
error smaller

我知道updateError不返回任何東西,這可能導致未定義的行為。

沒有“可以”。 您的代碼具有未定義的行為。 期。

在調試時,編譯器會做一些額外的工作來增強調試器的使用。 這可以像是實際上不必初始化變量時那樣。 在優化的構建中不會完成這種開銷。 無論如何,如果您想了解為什么獲得結果,那么您應該看一下組裝。 請注意,UB是UB,因此您無法保證在第二天使用相同的編譯器可獲得相同的結果。

我不明白的是,如果使用-O3進行編譯,則該錯誤在循環內設置為零,並且if(error> eps)的評估為false,而while()語句中的評估為true。

請注意,您編寫的代碼不會逐行轉換為CPU的指令。 編譯器非常聰明,並且會在視情況規則下應用各種轉換。 只要可觀察到的行為是相同的,編譯器就可以將您的代碼轉換為與天真的逐行轉換完全不同的東西。 但是,如果您的代碼具有UB,則它不是有效的c ++代碼,並且對於一個相同的變量獲取不同的輸出並不令人感到意外。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM