[英]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.