5 回答

TA貢獻(xiàn)1852條經(jīng)驗(yàn) 獲得超1個贊
我發(fā)現(xiàn)的最佳解釋是Mike Acton,了解嚴(yán)格別名。它主要關(guān)注PS3開發(fā),但這基本上只是GCC。
來自文章:
“嚴(yán)格別名是由C(或C ++)編譯器做出的一個假設(shè),即取消引用指向不同類型對象的指針永遠(yuǎn)不會引用相同的內(nèi)存位置(即彼此別名)?!?/p>
所以基本上如果你有一個int*
指向包含一個內(nèi)存的內(nèi)存int
然后你指向一個float*
內(nèi)存并將其用作float
你打破規(guī)則。如果您的代碼不遵守這一點(diǎn),那么編譯器的優(yōu)化器很可能會破壞您的代碼。
規(guī)則的例外是a char*
,允許指向任何類型。

TA貢獻(xiàn)1773條經(jīng)驗(yàn) 獲得超3個贊
這是嚴(yán)格的別名規(guī)則,可以在C ++ 03標(biāo)準(zhǔn)的3.10節(jié)中找到(其他答案提供了很好的解釋,但沒有提供規(guī)則本身):
如果程序試圖通過不同于以下類型之一的左值訪問對象的存儲值,則行為未定義:
對象的動態(tài)類型,
一個cv限定版本的動態(tài)類型的對象,
與對象的動態(tài)類型對應(yīng)的有符號或無符號類型的類型,
一種類型,是有符號或無符號類型,對應(yīng)于對象動態(tài)類型的cv限定版本,
一種聚合或聯(lián)合類型,包括其成員中的上述類型之一(包括遞歸地,子聚合或包含聯(lián)合的成員),
一個類型,它是對象動態(tài)類型的(可能是cv限定的)基類類型,
a
char
或unsigned char
類型。
C ++ 11和C ++ 14措辭(強(qiáng)調(diào)變化):
如果程序試圖通過以下類型之一以外的glvalue訪問對象的存儲值,則行為未定義:
對象的動態(tài)類型,
一個cv限定版本的動態(tài)類型的對象,
與對象的動態(tài)類型類似的類型(如4.4中所定義),
與對象的動態(tài)類型對應(yīng)的有符號或無符號類型的類型,
一種類型,是有符號或無符號類型,對應(yīng)于對象動態(tài)類型的cv限定版本,
聚合或聯(lián)合類型,包括其元素或非靜態(tài)數(shù)據(jù)成員中的上述類型之一(遞歸地,包括子聚合或包含聯(lián)合的元素或非靜態(tài)數(shù)據(jù)成員),
一個類型,它是對象動態(tài)類型的(可能是cv限定的)基類類型,
a
char
或unsigned char
類型。
兩個變化很?。?em>glvalue而不是lvalue,以及聚合/聯(lián)合案例的澄清。
第三個變化提供了更強(qiáng)有力的保證(放寬強(qiáng)混疊規(guī)則):類似類型的新概念現(xiàn)在可以安全別名。
另外,?措詞(C99; ISO / IEC 9899:1999 6.5 / 7;完全相同的措詞在ISO / IEC 9899中使用:2011§6.5?7):
對象的存儲值只能由具有以下類型之一(73)或88)的左值表達(dá)式訪問:
與對象的有效類型兼容的類型,
與對象的有效類型兼容的類型的限定版本,
與對象的有效類型對應(yīng)的有符號或無符號類型的類型,
與有效類型的對象的限定版本對應(yīng)的有符號或無符號類型的類型,
聚合或聯(lián)合類型,包括其成員中的上述類型之一(包括遞歸地,子聚合或包含聯(lián)合的成員),或者
一個字符類型。
73)或88)此列表的目的是指定對象可能或可能不具有別名的情況。

TA貢獻(xiàn)1995條經(jīng)驗(yàn) 獲得超2個贊
嚴(yán)格的別名不僅僅指向指針,它也會影響引用,我為boost開發(fā)人員wiki寫了一篇關(guān)于它的文章,并且它很受歡迎,我把它變成了我咨詢網(wǎng)站上的一個頁面。它完全解釋了它是什么,為什么它如此混淆了人們以及如何處理它。嚴(yán)格別名白皮書。特別是它解釋了為什么工會是C ++的危險行為,以及為什么使用memcpy是C和C ++中唯一可移植的解決方案。希望這是有幫助的。

TA貢獻(xiàn)1946條經(jīng)驗(yàn) 獲得超4個贊
作為Doug T.已經(jīng)寫過的補(bǔ)充,這里有一個簡單的測試用例,可能用gcc觸發(fā)它:
check.c
#include <stdio.h>void check(short *h,long *k){ *h=5; *k=6; if (*h == 5) printf("strict aliasing problem\n");}int main(void){ long k[1]; check((short *)k,k); return 0;}
編譯gcc -O2 -o check check.c
。通常(我嘗試過的大多數(shù)gcc版本)都輸出“嚴(yán)格別名問題”,因?yàn)榫幾g器假定“h”不能與“check”函數(shù)中的“k”相同。因此,編譯器優(yōu)化了if (*h == 5)
遠(yuǎn)離并始終調(diào)用printf。
對于那些感興趣的人是x64匯編程序代碼,由gcc 4.6.3生成,在ubuntu 12.04.2 for x64上運(yùn)行:
movw $5, (%rdi)movq $6, (%rsi)movl $.LC0, %edi jmp puts
所以if條件完全從匯編代碼中消失了。
- 5 回答
- 0 關(guān)注
- 918 瀏覽
添加回答
舉報