亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

什么是嚴格別名規則?

什么是嚴格別名規則?

四季花海 2019-05-21 14:50:30
當詢問C中常見的未定義行為時,靈魂比我提到的嚴格別名規則更加開明。他們在說什么?
查看完整描述

5 回答

?
小怪獸愛吃肉

TA貢獻1852條經驗 獲得超1個贊

我發現的最佳解釋是Mike Acton,了解嚴格別名。它主要關注PS3開發,但這基本上只是GCC。

來自文章:

“嚴格別名是由C(或C ++)編譯器做出的一個假設,即取消引用指向不同類型對象的指針永遠不會引用相同的內存位置(即彼此別名)?!?/p>

所以基本上如果你有一個int*指向包含一個內存的內存int然后你指向一個float*內存并將其用作float你打破規則。如果您的代碼不遵守這一點,那么編譯器的優化器很可能會破壞您的代碼。

規則的例外是a char*,允許指向任何類型。


查看完整回答
反對 回復 2019-05-21
?
慕容3067478

TA貢獻1773條經驗 獲得超3個贊

這是嚴格的別名規則,可以在C ++ 03標準的3.10節中找到(其他答案提供了很好的解釋,但沒有提供規則本身):

如果程序試圖通過不同于以下類型之一的左值訪問對象的存儲值,則行為未定義:

  • 對象的動態類型,

  • 一個cv限定版本的動態類型的對象,

  • 與對象的動態類型對應的有符號或無符號類型的類型,

  • 一種類型,是有符號或無符號類型,對應于對象動態類型的cv限定版本,

  • 一種聚合或聯合類型,包括其成員中的上述類型之一(包括遞歸地,子聚合或包含聯合的成員),

  • 一個類型,它是對象動態類型的(可能是cv限定的)基類類型,

  • charunsigned char類型。

C ++ 11C ++ 14措辭(強調變化):

如果程序試圖通過以下類型之一以外的glvalue訪問對象的存儲值,則行為未定義:

  • 對象的動態類型,

  • 一個cv限定版本的動態類型的對象,

  • 與對象的動態類型類似的類型(如4.4中所定義),

  • 與對象的動態類型對應的有符號或無符號類型的類型,

  • 一種類型,是有符號或無符號類型,對應于對象動態類型的cv限定版本,

  • 聚合或聯合類型,包括其元素或非靜態數據成員中的上述類型之一(遞歸地,包括子聚合或包含聯合的元素或非靜態數據成員),

  • 一個類型,它是對象動態類型的(可能是cv限定的)基類類型,

  • charunsigned char類型。

兩個變化很?。?em>glvalue而不是lvalue,以及聚合/聯合案例的澄清。

第三個變化提供了更強有力的保證(放寬強混疊規則):類似類型的新概念現在可以安全別名。


另外,?措詞(C99; ISO / IEC 9899:1999 6.5 / 7;完全相同的措詞在ISO / IEC 9899中使用:2011§6.5?7):

對象的存儲值只能由具有以下類型之一(73)或88)的左值表達式訪問:

  • 與對象的有效類型兼容的類型,

  • 與對象的有效類型兼容的類型的限定版本,

  • 與對象的有效類型對應的有符號或無符號類型的類型,

  • 與有效類型的對象的限定版本對應的有符號或無符號類型的類型,

  • 聚合或聯合類型,包括其成員中的上述類型之一(包括遞歸地,子聚合或包含聯合的成員),或者

  • 一個字符類型。

73)或88)此列表的目的是指定對象可能或可能不具有別名的情況。


查看完整回答
反對 回復 2019-05-21
?
拉風的咖菲貓

TA貢獻1995條經驗 獲得超2個贊

嚴格的別名不僅僅指向指針,它也會影響引用,我為boost開發人員wiki寫了一篇關于它的文章,并且它很受歡迎,我把它變成了我咨詢網站上的一個頁面。它完全解釋了它是什么,為什么它如此混淆了人們以及如何處理它。嚴格別名白皮書。特別是它解釋了為什么工會是C ++的危險行為,以及為什么使用memcpy是C和C ++中唯一可移植的解決方案。希望這是有幫助的。


查看完整回答
反對 回復 2019-05-21
?
絕地無雙

TA貢獻1946條經驗 獲得超4個贊

作為Doug T.已經寫過的補充,這里有一個簡單的測試用例,可能用gcc觸發它:

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。通常(我嘗試過的大多數gcc版本)都輸出“嚴格別名問題”,因為編譯器假定“h”不能與“check”函數中的“k”相同。因此,編譯器優化了if (*h == 5)遠離并始終調用printf。

對于那些感興趣的人是x64匯編程序代碼,由gcc 4.6.3生成,在ubuntu 12.04.2 for x64上運行:

movw    $5, (%rdi)movq    $6, (%rsi)movl    $.LC0, %edi
jmp puts

所以if條件完全從匯編代碼中消失了。


查看完整回答
反對 回復 2019-05-21
  • 5 回答
  • 0 關注
  • 935 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號