0

Cがスタックに変数を割り当てる方法を確認するために、いくつかの実験を行っています。次のコードで奇妙な動作が発生しています。C はスタックを下向きに成長させているように見えるため、次の例では、短い s の直前のバイトに char c が割り当てられます。次に、int ポインターbigRandPを作成し、c が占める位置と同じ場所を指すようにします。そのため、"int" は、s が占めるスタック上のスペースと重なります。次に、int ポインターが参照する場所に何かを割り当てようとします。

unsigned short nameSum = 0;
unsigned char smallRand = 0;
unsigned int* bigRandP;

//The "int" pointed to by iP should overlap s
bigRandP = (unsigned int*)(&smallRand);
printf("%p %p %p\n", &nameSum, &smallRand, bigRandP);
printf("%u %u %u\n", smallRand, nameSum, *bigRandP);
*bigRandP = 0;
printf("%p %p %p\n", &nameSum, &smallRand, bigRandP);
printf("%u %u %u\n", smallRand, nameSum, *bigRandP);

0028FF1A 0028FF19 0028FF19
0 0 419430400
0028FF1A 0028FF19 0028FF00
0 0 4210788

印刷結果は興味深いものです。割り当てが失敗するだけでなく (bigRandP が指す int が 0 に設定されていない)、int ポインター自体がサイレントに再配置され、スタックのさらに下の別の場所を指します。何が起こっている?これは、重複するポインタで他の変数を上書きしないようにする C コンパイラの方法ですか?

4

1 に答える 1

4

bigRandPへのポインタunsigned intです。

オブジェクトを指してから、指しているオブジェクトunsigned char変更しました。unsigned intbigRandP

どうやらsmallRandbigRandPはメモリ内で互いに近くに格納されています。1 バイト オブジェクトのバイトを変更しようとするsizeof (unsigned int)と、ポインター オブジェクト自体の一部が破壊されます。

結論: プログラムの動作は未定義です。

また、これはおそらく表示されている動作とは関係ありませんが、この%p形式にはvoid*引数が必要です。他のタイプのポインターを出力したい場合は、次のように変換する必要がありますvoid*

printf("%p %p %p\n", (void*)&nameSum, (void*)&smallRand, (void*)bigRandP);

すべてのポインターが同じ表現を持つシステムでは、キャストの有無にかかわらず「機能する」可能性がありますが、キャストを含むバージョンはすべてのシステムでより正確です。

于 2013-04-05T19:05:05.027 に答える