2
main()
{
    f();
}
int f( int i, float fl)
{
    printf("function");
}
  1. f ()が宣言される前に呼び出されているため、上記のコードが「C」で正常に実行されfunction、エラーを報告する必要があるときに出力されるのはなぜですか。

  2. 「C」で正常に実行されている場合は、「C++」では実行できません。C ++で実行すると、次のように表示されます。error: 'f' was not declared in this scope

  3. 宣言されていない関数が int を返し、指定されていない数の引数を受け入れるとコンパイラが想定しているなどの理由がある場合、以下の関数でも正常に実行されるのはなぜですか (つまり、戻り値の型をintではなくvoidに返す場合は?

void f ( int i, float fl)

{

    printf("function");

}

4

3 に答える 3

4
  1. C では関数の暗黙的な宣言が許可されているためです。または、少なくともそうでした。C90 では宣言が必要になる場合がありますが、わかりません。しかし、関数を宣言しないことは C では非常に長い間一般的な慣行であったため、禁止された後でも、ほとんどのコンパイラはそれを許可し続けると思います。

  2. C と C++ は別の言語だからです。C++ では、暗黙的に関数を宣言することは許可されていません。

  3. void歴史的に、C には型がありませんでした。戻り値のない関数は、何も返さなくても宣言されintており、(存在しない) 戻り値を使用しようとしない限り問題はありません。

于 2012-08-09T10:34:34.253 に答える
4
  1. C プログラミング言語の古いバージョンでは、以前の宣言なしで関数参照が許可されていました。遺産として、現在の多くのコンパイラは古い言語またはその側面をまだサポートしています。これが、一部のコンパイラがあなたが示したソース コードを受け入れる理由です。コンパイラには、より新しいバージョンの C プログラミング言語を使用するか、標準への準拠をより厳密にするように指示するスイッチが含まれている可能性があります。

  2. C++ は最近開発されたものであり、宣言のない関数の遺産はありません。

  3. アセンブリ言語はたまたま同じように実装されているため、さまざまな戻り値の型が機能します。void を返す関数の場合、呼び出されたルーチンは単にその操作を実行して戻ります。int を返す関数の場合、呼び出されたルーチンはその操作を実行し、その最終結果を特定のプロセッサ レジスタに入れ、戻ります。呼び出し側ルーチンでは、int を返す関数の戻り値が使用されない場合、呼び出し側ルーチンはプロセッサ レジスタの内容を単純に無視します。レジスタは無視されるため、呼び出し元のルーチンにとっては、void を返す関数と int を返す関数の間に違いはありません。これは、すべてのターゲット プラットフォームに当てはまるわけではありません。特に戻り値の型がより複雑なオブジェクト (構造体など) である場合は、戻り値の型が異なる関数間に違いが生じる可能性があります。と、呼び出し元の関数が戻り値を使用した場合、戻り値の型によって違いが生じます。void を返す関数は、戻り値があるはずのプロセッサ レジスタに制御されていない値を残し、呼び出し元の関数はそれを使用して予期しない結果を取得します。

明らかなように、これは信頼すべき動作ではありません。より厳密に標準に準拠し、より多くの警告が必要であることを指定するコンパイラ スイッチを使用することをお勧めします。(私はこれらがコンパイラのデフォルトであることを望みます。) そして、標準に準拠したコードを書くことは良い習慣です。

于 2012-08-09T10:35:01.717 に答える
0

コンパイラの呼び出しで適切なフラグを使用していないため、C ではエラーは表示されません。

あなたのコンパイラは何ですか?

の場合はgcc、試してくださいgcc -std=c99 -pedantic -Werror ...

于 2012-08-09T10:27:31.893 に答える