2013-01-21 55 views
12

C語言中的以下代碼是否具有已定義的行爲?從const指針中刪除const是否遵守C中的嚴格別名,並引用同一個對象?

int main() { 
    const int i = 0; 
    return *(int*)(&i); 
} 

我問,因爲6.5/7列出爲一個有效的別名「與有效對象的類型兼容的類型的合格版本」。但對象的有效類型是const int,我不認爲intconst int的合格版本(儘管情況正好相反)。 intconst int兼容(6.7.3/10)。

此外,6.3.2.3/2表示可以通過將指針類型轉換爲限定符,並且生成的指針是相等的。 6.3.2.3/7說你可以轉換任何兩種指針類型(所以鑄造(int*)(&i)本身是允許的)。但並不是說所產生的指針指向的是同一個對象,或者說它是平等的。它所說的是它可以轉換回原來的類型(在這種情況下爲const int*)。也就是說,即使別名是合法的,我也不清楚標準是否保證了我的指針轉換確實會產生一個指向i的指針。

那麼,標準實際上是否定義了我的代碼的行爲,如果是這樣定義的呢?

我知道代碼在實踐中的作品。我想到了一個假想的(和奇怪的)實現,它不起作用。我可以問這個實現是否符合標準(如果沒有,它違反了什麼部分),但是如果我的想象實現不符合其他方面,我不想渾水。如果有人認爲它會幫助他們回答這個問題,我會描述實施情況。

+0

對於轉換回int const *標準清楚地表明結果必須是標識。 「否則,當再次轉換時,結果應與原始指針相等。」 –

+0

@JensGustedt:同意。這對我的代碼沒有幫助,因爲我的代碼永遠不會將它轉換回'int const *'。 –

回答

7

它是由§6.7.3P5至少暗示它的工作原理,:

如果試圖通過使用左值的修改與 常量限定類型定義的對象使用非const限定的 類型時,行爲是未定義的。如果試圖通過使用非易失性限定類型的左值 來引用通過易失性限定類型定義的對象 ,則行爲是未定義的。

注意,對於volatile限定類型,它說,但對於const限定的類型,它只是說修改,這意味着非修改的訪問是OK(「來證明例外規則「)。

雖然在我看來,您可能已經發現了標準中的缺陷。

+0

我也認爲這應該是一個缺陷,但另一方面,這意味着我們知道const變量是如何實現的。 – Spidey

+1

我不同意:雖然常量限定沒有通過未定義的類型化表達式進行非修改訪問,但有效的鍵入規則仍然這樣做:不同的限定類型不兼容(除了通過參數確定函數類型的兼容性)和規則只是放寬*額外*資格的方向 – Christoph

+2

@Christoph:我同意這是嚴格閱讀別名規則的結果,但我的觀點是我不認爲這是*意圖*效果,因爲它會使我所引用的規範性段落完全沒有實際意義,也不能解釋爲什麼不同的措詞被用於常量和不穩定的情況。 – caf

相關問題