2015-05-01 68 views
3

我正在讀這本書http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html,我停下了其中一個例子。在我看來這是不正確的。我認爲,沒有不確定的行爲。我錯了嗎?在這裏它是:誤解代碼示例

隔空類型的數據對象,它是不常量和 的將其放入一個指向同一 類型的常量限定版本的地址是既安全又明確允許;你將能夠使用 指針來檢查對象,但不能修改它。把 一個const類型的地址放到一個指向非限定類型的指針上會更危險,因此被禁止(儘管你可以通過使用強制類型來得到 )。下面是一個例子:

#include <stdio.h> 
#include <stdlib.h> 

main(){ 
     int i; 
     const int ci = 123; 

     /* declare a pointer to a const.. */ 
     const int *cpi; 

     /* ordinary pointer to a non-const */ 
     int *ncpi; 

     cpi = &ci; 
     ncpi = &i; 

     /* 
     * this is allowed 
     */ 
     cpi = ncpi; 

     /* 
     * this needs a cast 
     * because it is usually a big mistake, 
     * see what it permits below. 
     */ 
     ncpi = (int *)cpi; 

     /* 
     * now to get undefined behaviour... 
     * modify a const through a pointer 
     */ 
     *ncpi = 0; 

     exit(EXIT_SUCCESS); 
} 

例8.3 如示例所示,也可以取爲恆定的對象的地址,>生成的指針 到非恆定,然後使用新指針。這是您的 程序中的錯誤,並導致未定義的行爲。

在此示例中,ncpi最終指向i而不是ci。所以我認爲這使得這個例子不正確—在通過指針修改非const變量時沒有未定義的行爲。你同意嗎?

+1

你爲什麼會認爲修改一個常量不是未定義的東西? –

+2

我不知道。因爲在這個例子中ncpi最後指向了我的位置,沒有ci。所以我認爲這使得這個例子不正確。你同意嗎? –

+0

請注意,如果你的問題提示「如果你的問題是」ncpi「最終指向」i「,而不是」ci「,那麼你的問題會得到更好的回答,而且沒有人會拖延錯誤路徑。所以我認爲這就是這個例子不正確,你同意嗎?「 –

回答

-2

它未定義,因爲它可能存儲在只讀存儲器中。在x86系統中情況並非如此,但是在這裏我們遇到了很多其他問題,如啓用大量優化時出現的別名問題。無論哪種方式,即使只是直觀地說,爲什麼你會認爲通過一個指向編譯器不能靜態驗證的指針來修改const將是安全的?

+1

最後ncpi指向我的位置,而不是ci。 ! –

4

我同意這是一個有缺陷的例子。代碼本身展現出定義的行爲。

最終作業前的註釋*ncpi = 0;與代碼不一致。可能作者打算做一些不同的事情。


我的第一個反應是如同代碼改寫一個const:     我已經修改了我的答案。

+1

它不會改變恆定的ci值,因爲最後ncpi指向我的位置,而不是ci。這沒有任何意義(我正在談論這本書中的例子)。 –

+0

@KarolisMilieška:你說的沒錯。我*假設代碼試圖寫入常量。也許作者認爲它也是如此,這就是爲什麼他/她的結論是書面的。評論當然說代碼是寫給一個'const'的。 – wallyk

+2

@wallyk:你不必保留所有原始文本的刪除線。它只是降低了信噪比,並沒有真正幫助答案。你可以繼續前進並刪除它(儘管你可以保留評論指出你的第一個反應是錯誤的;好奇的人可以檢查修訂歷史的答案)。 – Cornstalks