編譯器對操作的重新排序

2021-07-06 11:13:02 字數 1265 閱讀 7808

#include #include volatile int start[4];

volatile int done[4];

void *work(void *param)

printf("thread %i started\n", id);

double total = 0;

for(int i = 0; i < 100000000; i++)

printf("thread %i done\n", id);

done[id] = 1;

}int main()

for(int i = 0; i < 4; i++)

for(int i = 0; i < 4; i++) }

for(int i = 0; i < 4; i++)

}

有優化及無優化的輸出:

有優化的情況下,編譯器合併設定變數start和讀取變數done的兩個迴圈的**,產生的**和下面類似。

兩個迴圈不含函式呼叫,所以編譯器認為對volatile變數的訪問無***。因此,編譯器認為合併兩個迴圈是

安全的。

編譯器優化的**:

int main()

for(int i = 0; i < 4; i++) }

for(int i = 0; i < 4; i++)

}

使用gcc的asm("":::"memory"),可以使編譯器對迴圈正確排序。這條語句避免了迴圈合併,且不會像**增加

額外指令。

使用gcc的asm語句時操作順序正確:

int main()

for(int i = 0; i < 4; i++)

asm volatile("":::"memory");

for(int i = 0; i < 4; i++) }

for(int i = 0; i < 4; i++)

}

windows也為這一目的提供了內部函式。函式_readbarrier()、_writebarrier()和_readwritebarrier()在檔案中定義。這些內部函式告訴編譯器不要對這些操作重新排序。_readbarrier()呼叫確保所有讀操作在該點完成,_writebarrier()呼叫確保所有寫操作在該點完成。這些指令僅強制編譯器排序,但不生成任何指令。

Mac OS X作業系統的編譯器

在xcode中,可以使用三個編譯器 gcc4.2,llvm gcc 4.2,llvm complier clang 介面如下圖 gcc 還有乙個gcc 4.0版本提供 以上兩個圖上中的 llvm complier 2.0 和 clang 是同乙個東西。在macos上用xcode開發c c 程式,可以...

Mac OS X作業系統的編譯器

在xcode中,可以使用三個編譯器 gcc4.2,llvm gcc 4.2,llvm complier clang 介面如下圖 gcc 還有乙個gcc 4.0版本提供 以上兩個圖上中的 llvm complier 2.0 和 clang 是同乙個東西。在macos上用xcode開發c c 程式,可以...

VC編譯器與GCC編譯器的區別

今天無意寫了一段 發現了vc編譯器與gun的gcc編譯器還是存在區別的。畢竟gcc支援的是標準c。include struct node int main 上述 在gcc下是編譯失敗的,提示的錯誤 uknown typename node 但是放到vc編譯器下則順利編譯通過。於是按照標準c寫了另外乙...