allow the compiler to assume the strictest aliasing rules applicable to the language being compiled. for c (and c++), this activates optimizations based on the type of expressions. in particular, an object of one type is assumed never to reside at the same address as an object of a different type, unless the types are almost the same. for example, an unsigned int can alias an int, but not a void* or a double. a character type may alias any other type.
當使用strict aliasing時, 編譯器會認為在不同類型之間的轉換不會發生,是以執行更激進的編譯優化,例如reorder執行順序。
strcit aliasing隻能隐式的開啟或者顯式的禁止掉。在-o2或更高的編譯級别上會被隐式開啟。
函數的功能很簡單,對一個數字的高低位進行交換
gcc版本
執行strict aliasing (o2及以上預設打開)
非strict aliasing (顯式指定-fno-strict-aliasing)
不同的gcc flag,兩次的執行結果居然完全不相同,隻有第二次才實作了預期功能。因為預設情況下不報warning,我們把告警打開看看:
果然在使用strict aliasing時,因為破壞了嚴格aliasing的規則大量報警,是以如果我們要使用strict aliasing,一定要打開報警,并重視每個warning。
回到剛才的問題,為什麼strict aliasing會輸出最原始的資料,而不是修改後的資料呢 ? 看起來就好像後面的修改全部被忽略掉了一樣。 我們來看看編譯後的代碼。可以看到兩個彙編代碼完全不相同。編譯器認為代碼裡不可能出現不規範的類型轉換,是以在錯誤的案例裡,a的未被修改的值被直接抛給了printf函數
正确的 (gcc -o2 -fno-strict-aliasing x.c)
錯誤的 (gcc -o2 -fstrict-aliasing x.c)
但是如果我換成高版本的gcc,例如4.8版本,兩種編譯方式都沒有問題,甚至加上-wstrict-aliasing連報警都沒有。隻有加上-wstrict-aliasing=1才報warning
!!!無論如何, 如果你需要打開strict aliasing, 一定要打開wstrict-aliasing,消除代碼warning。 同時在代碼上也要盡量減少這種不同類型的轉換。
在mysql移除-fno-strict-aliasing後, 也看到了一些擔憂,因為mysql的codebase畢竟已經相當古老了, 而目前并沒有一些靜态或動态的分析工具能夠找到所有違反strict aliasing規則的地方。可能存在潛在的風險。