なぜ#include< stdio.h> printf()を使用する必要はありませんか?

StackOverflow https://stackoverflow.com/questions/336814

  •  22-07-2019
  •  | 
  •  

質問

セッションのトランスクリプト:

>type lookma.c
int main() {
  printf("%s", "no stdio.h");
}

>cl lookma.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

lookma.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:lookma.exe
lookma.obj

>lookma
no stdio.h
役に立ちましたか?

解決

厳密なコンプライアンスモード(「理論上」を意味します)では、スコープ内の関数のプロトタイプ宣言なしで可変数の引数を取る関数を呼び出すと、未定義の動作(悪い)を呼び出します。つまり、コンパイラーは、 #include< stdio.h> からのプロトタイプまたは同等の宣言なしで、 printf()を使用するプログラムで好きなことを行うことができます。 。 「好きなもの」"オプションの1つとして正しく動作することを含みます。それはあなたの例で選択されたオプションのようです。

実際には、 printf()関数の正式な宣言がなくても、ほとんどの実用的なコンパイラでコードは問題なく動作します。

qrdlが指摘したように、CコンパイラがCライブラリとリンクしているため、関数が見つかりました。

C99と「暗黙のint」に関するChris Youngのコメントは正確ですが、「変数引数関数はスコープ内にプロトタイプが必要」という規則はC89とC99の両方に適用されることに注意してください。ほとんどのコンパイラは、そのようにコンパイルできないコードが多すぎるため、デフォルトでは厳密なC99互換モードで動作しません。

Chris Youngのコメント:

  

明確にするために、私のコメントは、暗黙の宣言を削除するC99についてでした。 「暗黙のint」と言うことで、foo(void)などの宣言を許可するC89機能に言及していると思います。 int foo(void);を意味し、C99も削除されました。

もちろん、クリスは正しいです。 C99標準から2つの「暗黙的な宣言」機能が削除されました。標準の序文では、それらを次のようにリストしています:

  • 暗黙的な int
  • を削除します
  • 暗黙的な関数宣言を削除

私は十分に明確に考えていなかった(したがって、書いていなかった)。それでも、C89とC99の両方では、可変数の引数を取る関数のスコープ内にプロトタイプが必要です。

説明するには:

extern int pqr();
int main(void)
{
    int i = pqr(1, 3);
    return i;
}

最初の行がない場合、これは、整数(未指定の引数)を返す関数としての関数 pqr()の暗黙的な宣言を含む正しいC89フラグメントです。最初の行が extern pqr(); で置き換えられている場合、これは整数を返す関数として pqr()を明示的に宣言した正しいC89フラグメントです引数が指定されていない場合)、戻り値の型は 'implicit int 'です。書かれているように、関数は明示的に宣言されており、明示的な int 戻り値の型を持っていますが、未指定の引数が残っています。私はそれが有効なC99だと信じています-完全に望ましいものではありませんが。確かに、GCC(3.4.4)はオプション ' -std = c99 -pedantic "でそれを受け入れます。理想的には、関数宣言には完全なプロトタイプを含める必要があります。 (そして、 pqr()が省略記号で定義されている場合、そのプロトタイプは理論的には 必要です!)

他のヒント

もともとこのC ++にタグを付けていましたが、Cプログラムのように見えます。 Cは、スコープにプロトタイプがない場合(#include< stdio.h>の省略によるなど)、関数の暗黙的な宣言を自動的に提供します。暗黙の宣言は次のようになります。

int printf();

printfは、intを返す関数であり、任意の数の引数を取ることができることを意味します。このプロトタイプは、たまたまあなたの電話で機能していました。 #include< stdio.h>

最後に、現在のC標準(ISO / IEC 9899:1999または口語的には「C99」)が暗黙の宣言を 許可せず、このプログラムが適合しないことを追加する必要があります。暗黙の宣言は削除されました。コンパイラはC99をサポートしていないと思います。 C ++では正しいプロトタイプも必要であり、暗黙的な宣言は行いません。

printf()は標準Cライブラリにあり、リンカーは常に標準ライブラリを実行可能ファイルにリンクするため、標準関数が検出され、リンクの問題は発生しません。

適切なヘッダーをインクルードしないと、プロトタイプになっていない関数が使用され、問題が発生する可能性があります。Cコンパイラは、プロトタイプのない関数が int を返し、可変数の引数を取ると想定していますしたがって、常にヘッダーを含めてください-それはあなたの安全フェンスです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top