dポイントプレゼントキャンペーン実施中!

なぜgccはstdio.hをインクルードしなくてもprintfが実行できるのでしょうか。

暗黙にインクルードされるヘッダと
されないヘッダファイルの差分等あれば教えていただきたく。。

// main.c
int main(){
printf("SWSW\n") ;
return 0 ;
}
% gcc main.c
% ./a.out
SWSW

A 回答 (8件)

ごくおおざっぱに言えば、インクルードファイルの中には、



・グローバル変数
・typedef による型の定義
・sturcut や union や enum などユーザー定義の型(の定義)
・#define によるマクロ
・関数プロトタイプ
があります(その他のものもあります)

この中で、関数プロトタイプをのぞけば必須です。
ですから、NULL や EOF を使うには、(別に定義するのでなければ) stdio.h が必要です(だったかな?)

assert の実体は(関数ではなくて) #define によるマクロだった気がします(未確認・だとしたらインクルードは必須ですね)

さて、printf() の件ですが、これは、
printf("SWSW\n");
だったから(2番目以降の引数がないから)たまたま実行可能だったという可能性があります。
printf() は、可変引数(引数の数が決まっていない)関数なので、プロトタイプがないと、うまく処理できないコンパイラが多いです。
その場合でも、最初の引数の型決まっているので、引数がひとつだと、たまたま正常に実行可能です。
printf("%d, %f, %s", 1, 0.1, "STR");
なんかだとうまく処理できますでしょうか?
(これも未確認)

あと、関数の返値の型が int でないものは、プロトタイプがないと変な値が帰ってきます。
(ちなみに、printf() の返値は int です。あまり使われませんが)
    • good
    • 0

先ほど、リナックスの参考書を見てみると、print()関数は、内部でシステムコールを使っているとありました。


カーネルと結びつけられているからでは、ないでしょうか?
    • good
    • 0

> ”可変個引数を持つ関数を関数原型なしで呼び出した場合の動作は未定義”というのはどこで規定されているものなのでしょうか(C90?)。



JIS X3010:2003の「6.5.2.2 関数呼出し」の項には、

「呼び出される関数を表す式が,関数原型を含まない型をもつ場合,各実引数に対して整数拡張を行い,型floatをもつ実引数は型doubleに拡張する。この操作を既定の実引数拡張(default argument promotion)と呼ぶ。実引数の個数と仮引数の個数が等しくない場合,その動作は未定義とする。関数原型を含む型で関数を定義し,かつ,関数原型が省略(, ...)で終わっている場合,又は拡張後の実引数の型が,仮引数の型と適合しない場合,その動作は未定義である。」

という記述があります。
    • good
    • 0
この回答へのお礼

対応いただきありがとうございます。
納得しました。

お礼日時:2008/01/18 00:22

Cでは、関数原型(プロトタイプ)が宣言されていない状態でも関数を呼び出すことができます。

しかし、printfのような可変個引数を持つ関数を関数原型なしで呼び出した場合の動作は未定義です。動作が未定義の場合、特定の振る舞いをするように処理系を実装しても構わないので、GCCではまともに実行できるというだけです。

assertは、既に回答が出ているようにマクロですので、<assert.h>を必ずインクルードしなければなりません。
    • good
    • 0
この回答へのお礼

ありがとうございます。

assertについてはマクロ実装との事で理解しました。
”可変個引数を持つ関数を関数原型なしで呼び出した場合の動作は未定義”というのはどこで規定されているものなのでしょうか(C90?)。

お礼日時:2008/01/17 00:39

既に書かれているように, assert は assert.h で定義されるマクロです (というか, assert の機能をマクロ以

外で実現する方法が存在しない)... と規格に書いてある. だから, assert.h を #include しないと使えません.
    • good
    • 0

> assert関数は<assert.h>をincludeしないとコンパイルエラーになる



どういったコンパイルエラーが出ますか?
    • good
    • 0

1つは C ではプロトタイプ宣言が必須ではないこと, もう 1つは勝手に (printf などの実体の入っている) libc をリンクするから, かな.


ちなみにプロトタイプ宣言がない関数を呼び出した場合, 型 int()(...) をもつと仮定されるんじゃなかったかな.
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

プロトタイプ関数が必須でない事、libcに含まれているという事で理解しましたが、

assert関数は<assert.h>をincludeしないとコンパイルエラーになるのですが、この差分は何になるのかご存知でしょうか。

お礼日時:2008/01/16 20:52

>なぜgccはstdio.hをインクルードしなくてもprintfが実行できるのか


単に printf() の関数宣言をチェックしていないだけでしょう。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!