希望这是一个非常简单的问题。以下是我的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)
任何想法都赞赏!
答案 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
,它们会隐藏输入错误。请改用strtol
和strtod
。
答案 1 :(得分:2)
如果你没有另外指定,我相信C编译器只会猜测未声明的函数采用extern int foo()
形式。这就是为什么atoi
有效而atof
无效的原因。你使用哪些编译器标志?我建议使用-Wall
打开一堆gcc警告,其中应包括引用未声明的函数。
答案 2 :(得分:2)
C允许您在没有该函数声明的情况下调用函数。
假设该函数返回int
,并且将使用默认促销传递参数。如果那些与函数实际期望的不匹配,则会得到未定义的行为。
编译器经常会警告这种情况,但并非总是如此(这也取决于编译器配置)。
答案 3 :(得分:1)
在C中,当您使用未声明的函数时,它假定它具有默认原型:
int FUNCTION_NAME();
请注意,在C中使用()作为原型意味着它接受任何参数。
如果使用标志-Wall进行编译(我建议您始终使用此标志,因为它启用了所有建议的警告),您将收到警告(而不是错误),告诉您正在使用未声明的函数。
答案 4 :(得分:0)
atoi
会返回int
,因此它可以正常运行。 atof
没有,因此它无法正常工作。缺少原型/声明,你会得到未定义的行为 - 通常它最终会检索寄存器中通常会返回int
的任何值,并使用它。看来,在你的特定情况下,恰好是零,但它可能很容易成为别的东西。
这是许多人推动“C ++作为更好的C”的原因之一 - C ++确实要求在使用之前声明所有函数,并且还要指定所有(非可变参数)参数的类型(即C ++函数声明就像C原型,而不是C声明。)