不包括stdlib.h不会产生任何编译错误!

时间:2011-01-25 23:38:58

标签: c gcc std atof

希望这是一个非常简单的问题。以下是我的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)

任何想法都赞赏!

5 个答案:

答案 0 :(得分:12)

由于历史原因 - 具体而言,与非常旧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也不使用atof,它们会隐藏输入错误。请改用strtolstrtod

答案 1 :(得分:2)

如果你没有另外指定,我相信C编译器只会猜测未声明的函数采用extern int foo()形式。这就是为什么atoi有效而atof无效的原因。你使用哪些编译器标志?我建议使用-Wall打开一堆gcc警告,其中应包括引用未声明的函数。

答案 2 :(得分:2)

C允许您在没有该函数声明的情况下调用函数。

假设该函数返回int,并且将使用默认促销传递参数。如果那些与函数实际期望的不匹配,则会得到未定义的行为。

编译器经常会警告这种情况,但并非总是如此(这也取决于编译器配置)。

答案 3 :(得分:1)

在C中,当您使用未声明的函数时,它假定它具有默认原型:

int FUNCTION_NAME();

请注意,在C中使用()作为原型意味着它接受任何参数。

如果使用标志-Wall进行编译(我建议您始终使用此标志,因为它启用了所有建议的警告),您将收到警告(而不是错误),告诉您正在使用未声明的函数。

答案 4 :(得分:0)

遗憾的是,不需要在使用前对函数进行原型化(甚至声明) - 但是如果没有原型,它会自动对函数做出某些假设。其中之一是它返回一个int。在您的情况下,atoi会返回int,因此它可以正常运行。 atof没有,因此它无法正常工作。缺少原型/声明,你会得到未定义的行为 - 通常它最终会检索寄存器中通常会返回int的任何值,并使用它。看来,在你的特定情况下,恰好是零,但它可能很容易成为别的东西。

这是许多人推动“C ++作为更好的C”的原因之一 - C ++确实要求在使用之前声明所有函数,并且还要指定所有(非可变参数)参数的类型(即C ++函数声明就像C原型,而不是C声明。)