次のコードを考えてみましょう:xyyzy
のプロトタイプは、使用の時点では未知であるが、プロトタイプを持たない関数のデフォルトの戻り値の型がそうint
あるので、これはC89モードで動作し、今c99モードでgccが暗黙の関数宣言を間違って実行していますか?
int main (void) {
int i = xyzzy();
return i;
}
int xyzzy (void) {
return 42;
}
を暗黙関数プロトタイプと実際の関数は互換性があります。
そして、あなたはfloat
に、関数の戻り値の型を変更した場合(予想通り)実際には、あなたが得る:
testprog.c:6: error: conflicting types for 'xyzzy'
testprog.c:2: error: previous implicit declaration of 'xyzzy' was here
暗黙のプロトタイプと実際の機能はもはや一致ので。
C89は3.7.1 Function definitions
に言って、この持っているので、期待されている
testprog.c: In function 'main':
testprog.c:2: warning: implicit declaration of function 'xyzzy'
:
int型のextern int型の最大値を(、
gcc --std=c89 --pedantic -Wall -Wextra
でコンパイルされた元のコードは、私だけに警告を与えますint b){...}:ここではextern
はストレージクラス指定子であり、int
は型指定子です(それぞれ省略可能な場合もあります)。関数呼び出しに括弧で囲まれた引数リストの前の式は、単に識別子で構成されており、何の宣言は、この識別子のために表示されていない場合は、識別子が暗黙的に宣言されている場合は:
と
まったく同じように、 を含む最も内側のブロックでは、宣言は extern int identifier();が表示されます。3.3.2.2 Function calls
で
ので、それを宣言するまでの機能を使用することは間違いなく、デフォルトのプロトタイプで結果が作成される。
呼び出される関数を表し、式がオブジェクトを返す関数へのポインタ型を持つ場合:しかし、両方のこれらのフレーズがC99で削除されていると我々は代わりに(私の太字)
6.5.2.2 Function calls
で見つける
関数呼び出し式は、そのオブジェクト型と同じ型を持ち、6.8.6.4で指定された値を持つ。 それ以外の場合は、関数呼び出しにvoid型があります。
私はあなたが関数を呼び出すしようとすると、それは暗黙的にvoid
戻り値の型で宣言されたの視界には宣言がありませんならば、それは、それを意味するように理解しています。
gcc --std=c99 --pedantic -Wall -Wextra
でコンパイルすると、暗黙の宣言についても同じ警告が表示されます。
c99は暗黙のうちに関数void
を返すように宣言してはいけませんか?もしそれがあったとすれば、私はを返して再宣言しようとしたときと似たエラーprevious implicit declaration
を期待していたでしょう。
ここにgcc
が壊れていますか、または標準で何かが欠けていますか?
sun/oracle ccコンパイラで-xc99オプションを指定し、funcにfloatを使用すると、current:function(void)returns float; previous:function()戻り値int: "pax.c"、2行目。私はそれが難しいと思う2つの異なるコンパイラは、たとえ不可能ではないにしても、標準の同じ誤解を示しています - 標準は、物事がどうなるかを得るのを難しくする言語を避けるべきです! – ShinTakezou
@Shinは、Sunコンパイラのようにも見えますが、デフォルトではC99モードでも "intを返します"。この場合、私は標準を間違って読んでいる可能性があります。私はちょうどどこにいるのか分からなかった。 – paxdiablo
あなたは正しいとは言えません。後方互換性はありません。 C99では、関数または関数定義の宣言(できればプロトタイプ宣言)をスコープ内に表示することになっています。スコープ内の宣言は診断を必要としません(コンパイルに失敗する可能性があります)。 ISO C90のセクション番号は、C89 ANSI標準から引用しています。 –