この問題を説明するために使用する正しい用語がわかりませんが、最善を尽くします。
test.c で 12 と 13 の階乗を出力するおもちゃのプログラムを書いています。
#include <stdio.h>
int main(void)
{
printf("%ld\n", factorial(12));
printf("%ld\n", factorial(13));
return 0;
}
階乗関数は、ソースの fact.c を使用して共有ライブラリで定義されています。
long factorial(int n)
{
long r = 1;
while (n > 1) r *= n--;
return r;
}
次のコマンドを使用して、共有ライブラリとプログラムをコンパイルしています。
$ gcc -shared -fPIC -o libfact.so fact.c
$ gcc -L. -lfact test.c
私は x86-64 を使用しているので、factorial(13)
(13! = 6227020800) が 64 ビットの長さでオーバーフローしないことを期待しています。しかし、奇妙な結果が得られます。
$ LD_LIBRARY_PATH=. ./a.out
479001600
1932053504
ここで、1932053504 はたまたま正しい結果の下位 32 ビットの 10 進数値です。long factorial(int)
ただし、 test.c の先頭に関数プロトタイプを挿入して再コンパイルすると、正しい結果が得られます。
$ LD_LIBRARY_PATH=. ./a.out
479001600
6227020800
これにより、いくつかの質問が残ります。
- test.c でプロトタイプを指定しない場合、想定される戻り値の型は何ですか? このコンパイラは依存していますか?
- プロトタイプがなければ、任意の数の引数を に渡すことができるようです
factorial
。これは、C void 引数に関するこの質問と関数プロトタイプに関するこの質問に関連していますか? - リンカーが未定義の参照エラーをスローしないのはなぜですか?