著作一覧 |
なぜ、((unsigned long)v)
とせずに伸ばしてから論理積とか取ってるんだ?
AWDwRがあるはずないと思いながらも本屋に行ったら案の定なかったが、マイロボットとかいうムックがあったのでつい手に取ってみると妙に安い。各号に少しずつ部品が付いてくるのか。
ってことは最後に組み立て終わると武装蜂起するっていう仕組みだな。あぶないあぶない。
#include <stdio.h> long long calc(ll1, ll2) long long ll1; long long ll2; { return ll1 + ll2; } long long prot_calc(long long ll1, long long ll2) { return ll1 + ll2; } int main(int argc, char* argv[]) { printf("%lld\n", calc(-80, 128)); printf("%lld\n", prot_calc(-80, 128)); return 0; }をコンパイルして実行。
C:\DOCUME~1\arton\MYDOCU~1\test>cl test.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. test.c Microsoft (R) Incremental Linker Version 8.00.50727.42 Copyright (C) Microsoft Corporation. All rights reserved. /out:test.exe test.obj C:\DOCUME~1\arton\MYDOCU~1\test>test 18035912001912688 48
なるほど。
デフォルトはintなのがCだから、プロトタイプなしだとlong long(64ビット)ではなくint(32ビット)として引数を積むのが理由だろう。
というのを確認するにはアセンブラ出力を取れば良い。
VC++8の場合のアセンブラリストの出力オプションは"/Faファイル名"だ。
C:\DOCUME~1\arton\MYDOCU~1\test>cl /Fatest.asm test.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. test.c Microsoft (R) Incremental Linker Version 8.00.50727.42 Copyright (C) Microsoft Corporation. All rights reserved. /out:test.exe test.obj C:\DOCUME~1\arton\MYDOCU~1\test>type test.asm ……(snip)…… ; Line 16 push 128 ; 00000080H push -80 ; ffffffb0H call _calc add esp, 8 push edx push eax push OFFSET $SG2236 call _printf add esp, 12 ; 0000000cH ; Line 17 push 0 push 128 ; 00000080H push -1 push -80 ; ffffffb0H call _prot_calc add esp, 16 ; 00000010H push edx push eax push OFFSET $SG2237 call _printf
Line17(プロトタイプあり)のほうでは、push 0(正値)とpush -1(負値)が余分に入っていることが確認できる。
プロトタイプ無しのほうも、関数内部では64ビットずつスタックから引数を取り出すから、当然値はゴミになる(実際にはリターンアドレスとBPが取り出されるはずだから、特定の呼び出し単位に定数となる――再起呼び出しとかしたり動的にallocaしたりするとBPが変わるから定数ってのはちょっと大げさ)。
結論:int以外の引数をとるK&R関数呼び出しを見たら疑ってみよう。
問題:charやshortが引数の場合はどうなるか?
ジェズイットを見習え |