次のコードを検討してください。
int main (void) {
int i = xyzzy();
return i;
}
int xyzzy (void) {
return 42;
}
現在、プロトタイプxyyzy
は使用時に不明ですが、これは c89 モードで機能しますint
。これは、プロトタイプを持たない関数のデフォルトの戻り値の型が暗黙の関数プロトタイプと実際の関数に互換性があるためです。
実際、関数の戻り値の型を に変更するとfloat
、(予想どおり) 次のようになります。
testprog.c:6: error: conflicting types for 'xyzzy'
testprog.c:2: error: previous implicit declaration of 'xyzzy' was here
暗黙のプロトタイプと実際の関数が一致しなくなるためです。
でコンパイルされた元のコードでgcc --std=c89 --pedantic -Wall -Wextra
は、次の警告のみが表示されます。
testprog.c: In function 'main':
testprog.c:2: warning: implicit declaration of function 'xyzzy'
c89 には次のように記載されているため、これは予想されることです3.7.1 Function definitions
。
extern int max(int a, int b) { ... }:これ
extern
はストレージ クラス指定子でint
あり、型指定子です (これらはデフォルトであるため、それぞれを省略できます)。
とで3.3.2.2 Function calls
:
関数呼び出しで括弧で囲まれた引数リストの前にある式が識別子のみで構成され、この識別子の宣言が表示されない場合、識別子は、関数呼び出しを含む最も内側のブロックでextern宣言とまったく同じように暗黙的に宣言されます。 int識別子(); 現れた。
したがって、関数を宣言する前に関数を使用すると、デフォルトのプロトタイプが確実に作成されます。
ただし、これらのフレーズは両方とも c99 で削除されており、代わりに6.5.2.2 Function calls
(私の太字)が見つかります。
呼び出された関数を示す式がオブジェクト型を返す関数へのポインタ型を持つ場合、関数呼び出し式はそのオブジェクト型と同じ型を持ち、6.8.6.4 で指定されているように決定された値を持ちます。それ以外の場合、関数呼び出しの型は void です。
関数を呼び出そうとしたときにビューに宣言がない場合、void
戻り値の型で暗黙的に宣言されていることを意味すると理解しています。
それでも、でコンパイルするとgcc --std=c99 --pedantic -Wall -Wextra
、暗黙の宣言について同じ警告が表示されます。
c99 は、その関数を暗黙的に戻り値として宣言すべきではありませんでしたvoid
か? previous implicit declaration
もしそうなら、私はそれを return として再宣言しようとしたときに得たものと同様のエラーを期待していたでしょうfloat
.
ここで壊れていgcc
ますか、それとも標準に何か欠けていますか?