2012-09-06 99 views
4

我一直認爲像const int *a這樣的說法意味着aint指向const數據,因此不應該能夠修改它指向的值。事實上,如果你做const int a [] = {1,2,3},然後問題a[0] = 10你會得到編譯器錯誤。memcpy與目標指針常量數據

然而,令我驚訝的是,下面的代碼沒有任何警告,編譯運行得很好。

#include <stdio.h> 
#include <string.h> 

int main(){ 

    const int a [] = {1, 1, 1}; 
    const int b [] = {2, 2, 2}; 

    memcpy((void*) &a[0], (const void*)&b[0], 3*sizeof(int)); 

    int i; 
    for (i=0; i<3; i++) printf("%d\n",a[i]); 

    return 0; 
} 

爲什麼允許這樣做?這是由於演員?當我做memcpy(&a[0], (const void*)&b[0], 3*sizeof(int));編譯器迅速生成下列警告:

cpy.c: In function ‘main’: 
cpy.c:9:3: warning: passing argument 1 of ‘memcpy’ discards ‘const’ qualifier from pointer target type [enabled by default] 
/usr/include/string.h:44:14: note: expected ‘void * __restrict__’ but argument is of type ‘const int *’ 

回答

2

劇組通常會抑制警告。有一個海灣合作委員會的選項,-Wcast-qual會警告你失去constvolatile限定符的演員。

程序運行成功,因爲用於存儲數組的內存實際上不是隻讀的,因爲它們是分配在堆棧上的。這是一個實現細節,在技術上,如果實現非常嚴格,代碼可能會崩潰。

聲明ab作爲全局,有一個更大的機會,它會崩潰(仍然不能保證)

+1

報復指出 –

4

鑄造到void*消除與int協會 - 由扔掉的類型,你扔掉型裝飾,如const

編輯

從下面的討論中,我想明確一點,重要的一點不是你投的是什麼void*在OQ),但事實你施放 - 這意味着扔掉你的原始類型和它的裝飾。

+1

我不認爲這是正確的,你可以轉換爲'INT *',並會得到相同的結果。 –

+3

你想拍攝你的腿? - C不會阻止你。 – johannes

+0

+1 @Jesse - 代碼停止產生警告的原因是因爲'const'不見了,不是因爲它被鑄造成了'void *'。 –

5

您告訴編譯器忽略執行演員時的初始聲明。它聽了。這並不意味着你的程序是正確的。修改最初聲明爲const的內容會導致未定義的行爲(例如,編譯器可以將該數據存儲在只讀內存中)。

C不握住你的手。如果你選擇做危險的事情,那麼它會讓你。