2017-07-16 27 views
8

這是我的理解是這樣的事情是好的:int **和const int **可以替代別名嗎?

const int ci = 42; 
const int *cip = &ci; 
int *ip = (int *)cip; 
int j = *ip; 

這個怎麼樣?

const int ci = 42; 
const int *cip = &ci; 
const int **cipp = &cip; 
int **ipp = (int **)cipp; 
int j = **ipp; 
+0

int * ip =(int *)cip;'不好。你的編譯器應該抱怨丟掉'const'。如果不使用更高的警告等級。或者你想要什麼樣的「確定」? 「作品」,「可靠地工作」,「可移植作品」,「是很好的代碼」,... – Yunnosch

+7

@ Yunnosch:不。顯式強制轉換實際上就是你如何告訴編譯器你真的想要拋棄const。這就是你告訴編譯器不要發出任何警告的方式。第一個代碼片段是完全合法的C. – AnT

+0

@AnT對於所示的代碼,不需要去掉const。對於其他代碼有一個目的不是一個好主意。然而,我承認,我將編譯器警告與明確超級嚴格的靜態代碼分析器生成的nitpicky警告相混淆;我將在工作中用於代碼。他們不僅需要演員才能停止嘮叨。這有點讓我思考。 – Yunnosch

回答

5

表達*ippint *是類型的左值,然而它正用於訪問有效類型的const int *的對象。 (即,cip)。

根據該標準的字母,它是嚴格的別名違規:允許的別名類型的列表不包括別名T *作爲const T *,反之亦然。

最接近的例外是這一個:(C11 6.5/6摘錄)

  • 與有效類型的對象

的兼容的類型的一個合格的版本「合格版本「由C11 6.2.5/26明確定義:

每個不合格類型有幾個合格版本其類型,對應於const,volatilerestrict限定符中的一個,兩個或全部三個的組合。類型的合格或不合格 版本是屬於相同類型類別且具有相同表示和對齊要求的不同類型。派生類型不符合派生類型的限定符(如果有)。

所以異常是T可別名爲const T,反之亦然,但目前還沒有類似的例外指針aliasable類型。 const T *不是合格版本T *


然而當然還有的註腳:

這份名單的目的是,以指定的對象可能會或可能不會被混淆

這種情況下

我不能」說明規則的意圖是否爲const T *T *是可以別名的。對我來說,如果指定T *const T *具有「相同的表示和對齊要求」(6.2.5/28),如果它不是可以混淆的,這似乎還不清楚。

+1

保證只有在被視爲別名規則的例外時纔有用,這一事實不再意味着編譯器編寫者會將其解釋爲一個。除非在「沒有嚴格別名」模式下,通用初始序列保證在gcc和clang下基本沒有用處。前面已經說過,無論編譯器*還是*都假定'int * p'不會使用'int const ** p'來訪問,反之亦然;我不知道這是否會保持真實。 – supercat

相關問題