C 言語にはインクリメント演算子とデクリメント演算子という便利な演算子があります:
#include <stdio.h> int main () { int a = 5; --a; printf ("%d\n", a); return 0; }
上の例なら、変数 a は最終的に 4 になります。
では以下はどうなるでしょうか:
/* Practical C Programming (O'Reilly) 参照 */ #include <stdio.h> int main () { int a = 5; a = --a - a--; printf ("%d\n", a); return 0; }
答えは -1 です。以下のように分解すると分かりやすいです:
--a; a = a - a; a--;
実際、コンパイラ (gcc) は以下のようなアセンブリコードを出力します:
movl $5, 28(%esp) subl $1, 28(%esp) movl 28(%esp), %eax subl %eax, %eax movl %eax, 28(%esp) subl $1, 28(%esp)
スタック領域に long 型の 5 をコピーし、1 を引き、結果 (=4) を eax レジスタにコピーし、eax – eax し、結果をスタックにコピーし直し、さらに 1 を引く、という内容です。
ちなみに、書き下した C コードは微妙に異なるアセンブリコードに変換されました:
movl $5, 28(%esp) subl $1, 28(%esp) movl $0, 28(%esp) subl $1, 28(%esp)
なお、Python にインクリメント・デクリメント演算子が実装されない理由の 1 つに、上のような一見意味不明のコードを避けるということがあるようです (http://www.gossamer-threads.com/lists/python/dev/455027)。
※ 追記
gcc 4.6.3 で以下のコードをコンパイルすると、8 が表示されます:
/* Practical C Programming (O'Reilly) 参照 */ #include <stdio.h> int main () { int value; int result; value = 1; result = (value++ * 5) + (value++ * 3); printf ("%d\n", result); return 0; }
以下のようなイメージです:
value = 1; result = value * 5 + value * 3; value++; value++;
アセンブリコードは以下のようです:
movl $1, 28(%esp) # 28(%esp) = 1 movl 28(%esp), %edx # %edx = 1 movl %edx, %eax # %eax = 1 sall $2, %eax # %eax = 4 leal (%eax,%edx), %ecx # %ecx = 5 movl 28(%esp), %edx # %edx = 1 movl %edx, %eax # %eax = 1 addl %eax, %eax # %eax = 2 addl %edx, %eax # %eax = 3 addl %ecx, %eax # %eax = 8 movl %eax, 24(%esp) # 24(%esp) = 8 = result addl $1, 28(%esp) # 28(%esp) = 2 addl $1, 28(%esp) # 28(%esp) = 3 = value
結果はコンパイラ依存のようです。pcc 1.0.0 でコンパイルすると、13 が表示されます。
アセンブリコードは以下のようです:
movl $1,-4(%ebp) # -4(%ebp) = 1 movl -4(%ebp),%edx # %edx = 1 incl %edx # %edx = 2 movl %edx,-4(%ebp) # -4(%ebp) = 2 decl %edx # %edx = 1 imull $3,%edx # %edx = 3 movl -4(%ebp),%eax # %eax = 2 incl %eax # %eax = 3 movl %eax,-4(%ebp) # -4(%ebp) = 3 = value decl %eax # %eax = 2 imull $5,%eax # %eax = 10 leal (%eax,%edx),%eax # %eax = 13 movl %eax,-8(%ebp) # -8(%ebp) = 13 = result
トリッキーなコードは避けないといけませんね!
(コウヅ)
こういう式は未定義になります。
a = –a – a–;
色々解釈なさっていますが、「処理系依存」ではなくて「未定義」です。
未定義については以下を御覧ください。
http://www.kouno.jp/home/c_faq/c11.html
また以下に未定義の式の例があります。
http://www.kouno.jp/home/c_faq/c3.html#2
http://www.kouno.jp/home/c_faq/c3.html#9
こんにちは。だいぶ遅れましたが、コメントありがとうごさいます!RTFM のお手本みたいになっちゃいました ´^ω^`