5

const int *a私はいつも、 meansのようなステートメントaはデータへのintポインターでconstあり、そのため、それが指す値を変更できないはずだと思っていました。実際、実行しconst int a [] = {1,2,3}てから発行すると、a[0] = 10コンパイラエラーが発生します。

ただし、驚いたことに、以下は警告なしにコンパイルされ、正常に実行されます。

#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 *’
4

3 に答える 3

5

キャストを実行したときに、最初の宣言を無視するようにコンパイラーに指示しました。聞いた。しかし、それはあなたのプログラムが正しいという意味ではありません。最初に宣言されたものを変更するとconst、未定義の動作が発生します(たとえば、コンパイラはそのデータを読み取り専用メモリに自由に格納できます)。

Cはあなたの手を握っていません。あなたが何か危険なことをすることを選んだなら、それはあなたを許します。

于 2012-09-06T23:03:16.113 に答える
4

キャストしvoid*て-との関連付けを削除しintます。型を破棄することで、次のような型デコレータを破棄します。const

編集

以下の説明から、重要な部分は( OQで)キャストするものではなく、キャストするという事実であるということを明確にしておきます。これは、元のタイプとそのデコレータを破棄することを意味します。void*

于 2012-09-06T23:00:29.873 に答える
3

キャストは通常​​、警告を抑制します。または修飾子-Wcast-qualを失っているキャストについて警告するgccオプションがあります。constvolatile

配列を格納するために使用されたメモリがスタックに割り当てられていたため、実際には読み取り専用ではなかったため、プログラムは正常に実行されました。これは実装の詳細であり、技術的には、実装が本当に厳密な場合、コードがクラッシュする可能性があります。

宣言ab、グローバルとして、クラッシュする可能性が高くなります(まだ保証されていません)

于 2012-09-06T23:04:38.917 に答える