C/C++ が下手だとは言えませんが、興味深い構文に遭遇しました。私はこのコードを持っています:
int i=7;
char* m=(char*)&i;
m[2]=9;
cout<<i;
その出力は589831です。誰かがここで何が起こっているのかを詳しく説明できますか.
C/C++ が下手だとは言えませんが、興味深い構文に遭遇しました。私はこのコードを持っています:
int i=7;
char* m=(char*)&i;
m[2]=9;
cout<<i;
その出力は589831です。誰かがここで何が起こっているのかを詳しく説明できますか.
{ 07, 00, 00, 00 }
{ 07, 00, 09, 00 }
簡単に言えば、これはマルチバイト整数で個々のバイトを操作する方法の例です。
整数i
はおそらく 4 バイトで、最初に最小値 (リトル エンディアン) で配置されます。メモリでは、値は次のようになります。
0x07 0x00 0x00 0x00
インデックス 2 の値を変更したので、次のようになります。
0x07 0x00 0x09 0x00
バイトを逆にして元に戻すと、16 進数の 0x00090007 になり、10 進数の 589831 と同じになります。
整数アドレスを にキャストし、char*
配列表記を使用して変更しています。このステップ
m[2] = 9;
ポインタ演算と同じ
*(m+2) = 9;
つまり、アドレスm
+ 2 バイトのバイトを変更しています。したがって、初期整数値のバイトの 1 つ (3 番目) を変更しました
これが何が起こっているかの私の内訳であり、次に説明です。
// An integer on the stack, probably 4 bytes big, but we can't say that for sure.
int i=7; // Looks like 0x0000007 in memory. Endianness needs to be considered.
// Treat that integer as a \0 terminated string.
char* m=(char*)&i; // Acts as an empty string since the first byte is a 0, but we can't count on that.
// Set the second byte to 9.
m[2]=9; // Results in i being 0x00090007 (589831 decimal) on whatever architecture you are running. Once again, can't count on it.
// Print the modified integer.
cout<<i;
これは、3 つの理由から、信じられないほど危険で愚かなことです...
アーキテクチャのエンディアンを当てにするべきではありません。あなたのコードは、 が何であるかの基本的な表現が異なる CPU で実行される可能性がint
あります。
int
常に 4 バイトであるとは期待できません。
これで、文字列操作を実行するとクラッシュする可能性があるchar*
ことがわかりました。あなたの特定のケースでは、空の文字列を出力しますが、その整数に 0 バイトが含まれておらず、スタックの他の部分を読み続けるのにそれほど時間はかかりません。
本当に、本当に、本当にこれを行う必要がある場合、推奨される方法はユニオンを使用することですが、この種のちょっとしたいじりは非常にエラーが発生しやすく、ユニオンはほとんど役に立ちません。
int i=7
整数用に4バイトのメモリを予約し、CPUアーキテクチャに応じて(あなたがi86であるとしましょう)、メモリ内にこのようなものを生成します
7 0 0 0
次に、 の先頭を指すように作成されたポインター m 7 0 0 0
。afterm[2] = 9
メモリは次のようになります
7 0 9 0
(配列はゼロベースです);
次に、私を印刷します