記事『だからCってやつは *p++』に乱入してみるよ!
はお。
ちょっと面白そうだったので乱入してみようと思いますw
AyumiKatayamaさんの以下の記事……
*p++ に翻弄されているご様子。読んでいて混乱しますし、後置++ の優先順位が高いとか マジか って思ったので調査です調査!
前置きはなしで、じゃんっ!
挙動の確認できるテストプログラムのアセンブラを紐解いていきましょう。C側のソースでは 9行目ですね。アセンブラでは 19行目~ 24行目になりまする。
とその前にちゃんと見ていかないとね。冒頭の変数初期化部分。Cでは、
int v = 1;
int c = 0;
int* p = &v;
となり、アセンブラでは、
mov DWORD PTR _v$[ebp], 1
mov DWORD PTR _c$[ebp], 0
lea eax, DWORD PTR _v$[ebp]
mov DWORD PTR _p$[ebp], eax
となっています。これは変数 v のアドレス部に 1を代入、変数 c のアドレス部に 0を代入、ポインタ p は、eax レジスタに v のアドレスを入れて、変数 p(v) のアドレス部に eax レジスタの内容を代入していると分かれば OKです。
これを踏まえたうえで c = *p++ を見ていきましょう。
じゃん。
mov ecx, DWORD PTR _p$[ebp]
mov edx, DWORD PTR [ecx]
mov DWORD PTR _c$[ebp], edx
mov eax, DWORD PTR _p$[ebp]
add eax, 4
mov DWORD PTR _p$[ebp], eax
うわぁ、なんかごちゃごちゃするので必要なものだけにしてみます。
mov ecx , _p$[ebp]
mov edx , [ecx]
mov _c$[ebp], edx
mov eax , _p$[ebp]
add eax , 4
mov _p$[ebp], eax
なんとなく見やすくなったかな?
この中で注目すべきは add の部分、これが ++ に相当するところですね。その前の行で eax レジスタに p(v) のアドレス値を入れています。そして add で eax レジスタに 4 加算するとアドレスが 4 進むわけですね。つまり p++
始めの 3行では c = *p が行われています。ecx レジスタに p(v) のアドレス値を入れ、edx レジスタには ecx(アドレス)の実体を入れています。そして c に edx を入れて c = *p の完成でっす。
処理的には c = *p が先に行われ、次に p++ が処理されていますね…… 優先順位とかもうよくわかりません(==;
とりあえず、後置++ の挙動の確認が取れたのでよしとしましょう!(ぉ
悉く書を信ずれば則ち書無きに如かず