インクリメントはいつ行われる?
昨日のよくわからない問題ですが、以下のような簡単なチェックをしてみたところ挙動がわかりました。
int j=0; printf("j = %d, j++ = %d\n",j,j++);
//Releaseビルド(最適化:実行速度)だと 出力:j = 0, j++ = 0 混合モード push 0 push 0 push offset string "j = %d, j++ = %d\n" (413490h) call printf (40B5D4h)
//Releaseビルド(最適化:無効) 出力:j = 0, j++ = 0 混合モード mov dword ptr [j],0 mov eax,dword ptr [j] mov dword ptr [ebp-5Ch],eax mov ecx,dword ptr [ebp-5Ch] push ecx mov edx,dword ptr [j] push edx push offset string "j = %d, j++ = %d\n" (4154A8h) call printf (40D515h) add esp,0Ch mov eax,dword ptr [j] add eax,1 mov dword ptr [j],eax
//Debugビルドだと 出力:j = 1, j++ = 0 混合モード mov eax,dword ptr [j] mov dword ptr [ebp-15Ch],eax mov ecx,dword ptr [j] add ecx,1 mov dword ptr [j],ecx mov edx,dword ptr [ebp-15Ch] push edx mov eax,dword ptr [j] push eax push offset string "j = %d, j++ = %d\n" (45E404h) call @ILT+5575(_printf) (41F5CCh) add esp,0Ch
ちなみにこうするとDebugモードでは printf("j++ = %d, j = %d\n",j++,j); 出力:j++ = 0, j = 1
ふむふむ。混合モードなんて普段は見向きもしませんが、一つの文だけをアセンブラで見てみればそんなに難しいものではないんですね。なかなか面白いです。DebugとReleaseで違うのは最適化のせいかなとも思いましたが、Releaseビルドの最適化を無効にしても出力は変わりませんでした。
この中では最適化無効時のビルドが一番納得できる形ですけど、同じ式の中に同じ変数を入れてインクリメントするときの順番ってのは決まってないのかな。