別名和有效型別
違反別名規則和違反物件的有效型別是兩回事,不應混淆。
-
別名是兩個指標
a
和b
的屬性,它們指的是同一個物件,即a == b
。 -
C 使用資料物件的有效型別來確定可以對該物件執行哪些操作。特別地,有效型別用於確定兩個指標是否可以彼此別名。
別名可能是優化的問題,因為通過一個指標改變物件,a
說,可以改變通過另一個指標 b
可見的物件。如果你的 C 編譯器必須假設指標總是可以互為別名,無論它們的型別和來源如何,許多優化機會都會丟失,並且許多程式執行速度會變慢。
C 的嚴格別名規則是指編譯器中的情況可以假設哪些物件相互做(或不相互)別名。對於資料指標,你應始終牢記兩條經驗法則。
除非另有說明,否則具有相同基型別的兩個指標可能是別名。
具有不同基型別的兩個指標不能別名,除非這兩種型別中的至少一種是字元型別。
這裡基型別意味著我們放棄了 const
等型別資格,例如,如果 a
是 double*
而 b
是 const double*
,編譯器通常必須假設*a
的更改可能會改變*b
。
違反第二條規則可能會產生災難性後果。這裡違反嚴格的別名規則意味著你向編譯器提供兩個不同型別的指標 a
和 b
,它實際上指向同一個物件。然後,編譯器可能總是假設兩者指向不同的物件,並且如果你通過*a
更改了物件,則不會更新其對*b
的想法。
如果這樣做,程式的行為將變得不確定。因此,C 對指標轉換施加了相當嚴格的限制,以幫助你避免意外發生這種情況。
除非源或目標型別是
void
,否則具有不同基型別的指標之間的所有指標轉換必須是顯式的。
或者換句話說,他們需要一個演員陣容,除非你進行轉換隻是將一個限定符如 const
新增到目標型別。
一般來說,避免指標轉換和特別是強制轉換會保護你免受別名問題的影響。除非你真的需要它們,並且這些情況非常特殊,你應該儘可能地避免它們。