以下のプログラムは、<stdio.h>
?を含めずに動作しています。なぜこれが機能するのですか?
int main()
{
printf("integra");
return 0;
}
以下のプログラムは、<stdio.h>
?を含めずに動作しています。なぜこれが機能するのですか?
int main()
{
printf("integra");
return 0;
}
printf() の定義は libc.so にあり、ヘッダー ファイルをインクルードしなくてもダイナミック リンカが処理します。コンパイル時に、printf() は未定義のシンボルになり、後で libc で定義が見つかる可能性があると想定します。ヘッダー ファイルはプロトタイプの型を指定するだけで、プロトタイプの定義が glibc に存在することを示すコンパイラ (警告) を抑制します。したがって、基本的には、開発者を支援するために、定義がライブラリで利用可能であることを確認するためだけにヘッダー ファイルが含まれています。
古い標準では、宣言されていない関数はint
引数と戻り値を想定します。とchar*
同じサイズ (32 ビット)int
であるため、すべてが機能します。
やらないでください。
printf()はlibc.soでのみ定義されています
ダイナミックリンカは、libcにシンボルprintf()を含めていないため、それを解決します。
libcは、すべてのプログラムのgccのデフォルトです。
Abi が指摘したように、リンカは未定義のシンボル ( printf
) のシステム std ライブラリにデフォルト設定されているため、stdio.h をインクルードせずにコードが正常にビルドされます。GCC は通常、そのような場合に警告します。
test.c を次のようにします。
1: int main()
2: {
3: printf("test\n");
4: return 0;
5: }
Mac OSX で GCC 4.2.1 を使用して test.c をビルドする:
$ gcc test.c
test.c: In function ‘main’:
test.c:3: warning: incompatible implicit declaration of built-in function ‘printf’
$ ./a.out
test
このデフォルトのリンクを無効にするには、GCC リンカ オプション-nostdlib
(または-nodefaultlibs
) を-lgcc
(GCC マニュアルで推奨されているように) とともに指定します。
$ gcc -nostdlib -lgcc test.c
test.c: In function ‘main’:
test.c:3: warning: incompatible implicit declaration of built-in function ‘printf’
Undefined symbols:
"_puts", referenced from:
_main in cc3bvzuM.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
$
宣言されていない関数を使用すると、コンパイラは、この関数が を返し、int
指定されていないが固定数の引数を取ると想定します。
この仮定が関数の定義と一致し、指定した引数も (デフォルトの引数昇格を法として) 関数が受け取ることを期待するパラメーターと一致する場合、すべて問題ありません。
仮定が正しくない場合 (printf
可変引数関数である for のように)、または引数が一致しない場合、結果は未定義です。未定義の動作の厄介な点の 1 つは、期待どおりに動作しているように見えることです。
一部の (古い?) コンパイラは、関数を呼び出す前にプロトタイプを必要としません。