4

うまくいけば、これは非常に簡単な質問です。以下は、私が持っている C pgm (test.c) です。

#include <stdio.h>
//#include <stdlib.h>

int main (int argc, char *argv[]) {
    int intValue = atoi("1");
    double doubleValue = atof("2");
    fprintf(stdout,"The intValue is %d and the doubleValue is %g\n", intValue, doubleValue);
    return 0;
}

stdlib.h の atoi() と atof() を使用していますが、そのヘッダー ファイルは含めていません。pgm (gcc test.c) をコンパイルしましたが、コンパイラ エラーは発生しません。

pgm (./a.out) を実行すると、間違った出力が表示されます。

The intValue is 1 and the doubleValue is 0

ここで、(#include の前のコメントを削除して) stdlib.h をインクルードし、再コンパイルして再度実行します。今回は正しい出力が得られます。

The intValue is 1 and the doubleValue is 2

stdlib.h が含まれていないことについてコンパイラが文句を言わず、atoi()、atof() 関数を使用できるのはなぜですか?

私のgcc情報:

$ gcc --version
gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)

どんな考えでも大歓迎です!

4

5 に答える 5

13

歴史的な理由、特に非常に古い C プログラム (C89 より前)との互換性のため、最初に関数を宣言せずに関数を使用すると、エラーではなく GCC から警告が表示されるだけです。intしかし、そのような関数の戻り値の型はではなくであると見なされますdouble。これが、プログラムが正しく実行されない理由です。

-Wallコマンドラインで使用すると、診断が表示されます。

$ gcc -Wall test.c
test.c: In function ‘main’:
test.c:5: warning: implicit declaration of function ‘atoi’
test.c:6: warning: implicit declaration of function ‘atof’

-Wall基本的に常に使用する必要があります。新しいコードに対するその他の非常に便利な警告オプションは、、、、、およびですが-Wextra、それら-Wstrict-prototypesに比べて誤検知率がはるかに高くなります。-Wmissing-prototypes-pedantic-Wwrite-strings-Wall

atoi接線的に: norを使用しないatofでください。入力エラーを隠します。代わりにstrtolandを使用してください。strtod

于 2011-01-25T23:43:38.883 に答える
2

特に指定しない場合、C コンパイラは、宣言されていない関数が形式をとると推測するだけだと思いextern int foo()ます。これが機能する理由atoiatof機能しない理由です。どのコンパイラ フラグを使用していましたか? -Wall宣言されていない関数の参照を含む必要がある一連の gcc 警告を有効にするために使用することをお勧めします。

于 2011-01-25T23:41:21.187 に答える
2

C では、関数の宣言がなくても関数を呼び出すことができます。

関数は を返すと想定されint、引数はデフォルトの昇格を使用して渡されます。それらが関数が実際に期待するものと一致しない場合、未定義の動作が発生します。

多くの場合、コンパイラはこの場合に警告しますが、常にではありません (コンパイラの構成にも依存します)。

于 2011-01-25T23:42:27.050 に答える
1

C では、宣言されていない関数を使用すると、デフォルトのプロトタイプがあると想定されます。

int FUNCTION_NAME();

C で () をプロトタイプとして使用することは、任意の引数を受け入れることを意味することに注意してください。

フラグ -Wall (推奨されるすべての警告が有効になるため、常にこのフラグを使用することをお勧めします) を使用してコンパイルすると、宣言されていない関数を使用していることを示す警告 (エラーではありません) が表示されます。

于 2011-01-25T23:45:18.070 に答える
0

残念ながら、C では、関数を使用する前にプロトタイプを作成する (または宣言する) 必要はありませんが、プロトタイプがないと、関数に関する特定の仮定が自動的に作成されます。それらの 1 つは、int を返すことです。あなたの場合、 をatoi返すintので、正しく動作します。atofそうではないので、正しく動作しません。プロトタイプ/宣言がない場合、未定義の動作が発生しますint。通常、通常は が返されるレジスタにある値を取得し、それを使用することになります。あなたの特定のケースでは、それはたまたまゼロになるようですが、それは簡単に別のものになる可能性があります。

これは、多くの人が「C++ をより良い C として」推進する理由の 1 つです。C++ では、使用前にすべての関数を宣言する必要があり、さらにすべての (非可変個の) パラメータの型も指定する必要があります (つまり、C++関数宣言は、C 宣言とは異なり、C プロトタイプに似ています)。

于 2011-01-25T23:45:26.690 に答える