问题
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!
回答1:
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
, not double
, which is why the program executes incorrectly.
If you use -Wall
on the command line, you get a diagnostic:
$ 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’
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
nor atof
, they hide input errors. Use strtol
and strtod
instead.
回答2:
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 why atoi
works and atof
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.
回答3:
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).
回答4:
In C, when you use a function that was not declared, it assumes that it has the default prototype:
int FUNCTION_NAME();
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.
回答5:
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 an int
, 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 an int
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).
来源:https://stackoverflow.com/questions/4800102/not-including-stdlib-h-does-not-produce-any-compiler-error