トップ «前の日記(2006-02-26) 最新 次の日記(2006-02-28)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2006-02-27

_ 余分なこと

なぜ、((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が引数の場合はどうなるか?


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|

ジェズイットを見習え