質問

うまくいけば、これは非常に簡単な質問です。以下は、私が持っている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

次に、stdlib.h(#includeの前にコメントを削除することで)を含め、再コンパイルして再度実行します。今回は正しい出力を取得します:

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)

どんな考えも感謝します!

役に立ちましたか?

解決

歴史的な理由から - 具体的には、との互換性 非常に 古いCプログラム(PRE-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 または atof, 、入力エラーを非表示にします。使用する strtolstrtod 代わりは。

他のヒント

それ以外の場合は指定しない場合、Cコンパイラが未宣言の関数がフォームを取ると推測するだけだと思います extern int foo(). 。というわけで atoi 作品と atof そうではありません。どのコンパイラフラグを使用していましたか?使用することをお勧めします -Wall 宣言されていない関数の参照を含む必要があるGCC警告の束をオンにする。

Cを使用すると、その関数の宣言を持たずに関数を呼び出すことができます。

関数は、anを返すと想定されます int デフォルトのプロモーションを使用して引数は渡されます。それらが関数が実際に期待するものと一致しない場合、あなたは未定義の動作を得るでしょう。

コンパイラはしばしばこのケースについて警告しますが、常にではありません(そして、それはコンパイラ構成にも依存します)。

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

int FUNCTION_NAME();

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

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

Cは、残念ながら、使用前にプロトタイプ化(または宣言された)関数を必要としませんが、プロトタイプがなければ、関数について特定の仮定を自動的に行います。それらの1つは、INTを返すことです。あなたの場合、 atoi 返品します int, 、したがって、正しく動作します。 atof そうではないので、正しく機能しません。プロトタイプ/宣言がないので、未定義の動作が得られます。通常、レジスタ内の価値を取得することになります。 int 通常、返品され、それを使用します。あなたの特定のケースでは、それはたまたまゼロであるように見えますが、それは同じように簡単に何か他のものになる可能性があります。

これは、多くの人が「C ++をより良いC」とプッシュする理由の1つです。C++は、すべての関数を使用前に宣言することを要求し、さらにすべての(非バリアジック)パラメーターのタイプを指定することを要求します(つまり、C ++も同様です。関数宣言は、Cのプロトタイプのようなものであり、C宣言のようなものではありません)。

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