不包含 stdlib.h 不会产生任何编译器错误!
希望这是一个非常简单的问题。以下是我的 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 --version
gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)
任何想法表示赞赏!
Hopefully this is a very simple question. Following is the C pgm (test.c) I have.
#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;
}
Note that I am using atoi() and atof() from stdlib.h, but I do not include that header file. I compile the pgm (gcc test.c) and get no compiler error!
I run the pgm (./a.out) and here is the output, which is wrong.
The intValue is 1 and the doubleValue is 0
Now I include stdlib.h (by removing the comments before the #include) and recompile it and run it again. This time I get the right output:
The intValue is 1 and the doubleValue is 2
How come the compiler did not complain about not including the stdlib.h and still let me use the atoi(), atof() functions?
My gcc info:
$ gcc --version
gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)
Any thoughts appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
由于历史原因,特别是与非常旧的 C 程序(C89 之前)的兼容性,在没有首先声明的情况下使用函数只会引起 GCC 的警告,而不是错误。但此类函数的返回类型被假定为
int
,而不是double
,这就是程序执行不正确的原因。如果您在命令行上使用
-Wall
,您会得到一个诊断信息:您基本上应该始终使用
-Wall
。新代码的其他非常有用的警告选项有-Wextra
、-Wstrict-prototypes
、-Wmissing-prototypes
、-pedantic 和 -Wwrite-strings
,但与-Wall
相比,它们的误报率要高得多。切线:永远不要使用
atoi
或atof
,它们会隐藏输入错误。请改用strtol
和strtod
。For historical reasons -- specifically, compatibility with very old C programs (pre-C89) -- using a function without having declared it first only provokes a warning from GCC, not an error. But the return type of such a function is assumed to be
int
, notdouble
, which is why the program executes incorrectly.If you use
-Wall
on the command line, you get a diagnostic:You should use
-Wall
basically always. Other very useful warning options for new code are-Wextra
,-Wstrict-prototypes
,-Wmissing-prototypes
,-pedantic
, and-Wwrite-strings
, but compared to-Wall
they have much higher false positive rates.Tangentially: never use
atoi
noratof
, they hide input errors. Usestrtol
andstrtod
instead.如果您没有另外指定,我相信 C 编译器只会猜测未声明的函数采用
extern int foo()
的形式。这就是为什么atoi
有效而atof
无效的原因。您使用了哪些编译器标志?我建议使用 -Wall 来打开一堆 gcc 警告,其中应该包括引用未声明的函数。If you don't specify otherwise, I believe a C compiler will just guess that undeclared functions take the form
extern int foo()
. Which is whyatoi
works andatof
doesn't. Which compiler flags were you using? I suggest using-Wall
to turn on a bunch of gcc warnings, which should include referencing undeclared functions.C 允许您调用函数而无需声明该函数。
该函数将被假定返回一个
int
并且参数将使用默认的提升来传递。如果这些与函数实际期望的不匹配,您将得到未定义的行为。编译器通常会针对这种情况发出警告,但并非总是如此(这也取决于编译器配置)。
C allows you to call a function without having a declaration for that function.
The function will be assumed to return an
int
and arguments will be passed using default promotions. If those don't match what the function actually expects, you'll get undefined behavior.Compilers will often warn for this case, but not always (and that will also depend on compiler configuration).
在 C 中,当您使用未声明的函数时,它假定它具有默认原型:
请注意,在 C 中使用 () 作为原型意味着它接受任何参数。
如果您使用标志 -Wall 进行编译(我建议您始终使用此标志,因为它启用所有推荐的警告),您将收到一条警告(而不是错误),告诉您正在使用未声明的函数。
In C, when you use a function that was not declared, it assumes that it has the default prototype:
Note that in C using () as prototype means it accepts any arguments.
If you compile with the flag -Wall (I recommend you to always use this flag, since it enables all recommended warnings) you will get a warning (not an error) telling you that you are using an undeclared function.
不幸的是,C 不要求在使用函数之前对函数进行原型设计(甚至声明)——但是如果没有原型,它会自动对函数做出某些假设。其中之一是它返回一个 int。在您的情况下,
atoi
确实返回一个int
,因此它可以正常工作。atof
没有,因此它无法正常工作。缺少原型/声明,您会得到未定义的行为 - 通常它最终会检索通常返回int
的寄存器中恰好存在的任何值,并使用它。看来在您的特定情况下,它恰好是零,但它也可能很容易是其他值。这是许多人推崇“C++ 是更好的 C”的原因之一——C++ 确实要求在使用之前声明所有函数,并且还需要指定所有(非可变参数)参数的类型(即 C++函数声明就像 C 原型,而不是 C 声明)。
C, unfortunately, does not require functions to be prototyped (or even declared) before use -- but without a prototype, it automatically makes certain assumptions about the function. One of those is that it returns an int. In your case,
atoi
does return anint
, so it works correctly.atof
doesn't, so it doesn't work correctly. Lacking a prototype/declaration, you get undefined behavior -- typically it'll end up retrieving whatever value happens to be in the register where anint
would normally be returned, and using that. It appears that in your particular case, that happens to be a zero, but it could just as easily be something else.This is one of the reasons many people push "C++ as a better C" -- C++ does require that all functions be declared before use, and further that you specify the types of all (non-variadic) parameters as well (i.e. a C++ function declaration is like a C prototype, not like a C declaration).