Reputation: 2069
I write a "hello world" program in C:
void main()
{ printf("Hello World\n"); }
Note that I haven't included any header file.
The program compiles with warning as
vikram@vikram-Studio-XPS-1645:~$ gcc hello.c
hello.c: In function ‘main’:
hello.c:2:2: warning: incompatible implicit declaration of built-in function ‘printf’
vikram@vikram-Studio-XPS-1645:~$ ./a.out
Hello World
vikram@vikram-Studio-XPS-1645:~$
How is this possible? How does the OS link a library without including any header?
Upvotes: 4
Views: 2772
Reputation: 123448
The header usually1 contains only function declarations, symbolic constants, and macro definitions; it doesn't usually include function definitions.
All stdio.h
gives you is the prototype declaration for printf
:
int printf(const char * restrict format, ...); // as of C99
The implementation of printf
is in a separate library file that your code links against.
Your code "works" for two reasons:
Under C89 and earlier versions, if the compiler sees a function call
before a declaration or definition of that function, it will assume
that the function returns int
and takes an unspecified number of
parameters;
The implementation of printf
returns an int
, and you passed in
an argument that just happens to be compatible with what the
implementation of printf
expects for the first argument.
And to echo what everyone else says, use int main(void)
or int main(int argc, char **argv)
; unless your compiler documentation explicitly lists void main()
as a legal signature, using it will invoke undefined behavior (which means everything from your code running with no apparent issues to crashing on exit to failing to load completely).
Upvotes: 1
Reputation: 145829
In C, if you use a standard library function, you have to include the standard header where the function is declared. For printf
you have to include stdio.h
header file.
In C89 (and GNU C89 which is the language by default on gcc
), a function declaration can be sometimes omitted because there is a feature called implicit function declaration: when a function identifier foo
is used and the function has not been declared, the implementation would use this declaration:
/* foo is a function with an unspecified number of arguments */
extern int foo();
But this declaration is OK only for functions that return int
with an unspecified but fixed number of arguments. If the function accepts a variable number of arguments (like printf
) such program would invoke an undefined behavior.
Here is what C89/C90 says:
(C90, 6.7.1) "If a function that accepts a variable number of arguments is defined without a parameter type list that ends with the ellipsis notation, the behavior is undefined.
So gcc
is kind enough to compile even in C89 and GNU C89: a compiler could refuse to compile.
Also note that
void main() { ... }
is not a valid definition for main
(at least on hosted implementations which is probably your case).
If your main function doesn't take any argument use this valid definition:
int main(void) { ... }
Upvotes: 1
Reputation: 54971
The compiler builds your source file with a reference to a function called printf()
, without knowing what arguments it actually takes or what its return type is. The generated assembly contains a push
of the address of the string "Hello World"
in the static data area of your program, followed by a call
to printf
.
When linking your object file into an executable, the linker sees a reference to printf
and supplies the C standard library function printf()
. By coincidence, the argument you have passed (const char*
) is compatible with the declaration of the real printf()
, so it functions correctly. However, note that the printf()
that your program implicitly declares has return type int
(I think), which the standard printf()
also has; but if they differed, and you were to assign the result of calling printf()
to a variable, you would be in the land of undefined behaviour and you would likely get an incorrect value.
Long story short: #include
the correct headers to get the correct declarations for functions you use, because this kind of implicit declaration is deprecated, because it is error-prone.
Upvotes: 8
Reputation: 500287
hello.c:2:2: warning: incompatible implicit declaration of built-in function ‘printf’
To deal with this warning, you should include the header file (stdio.h
). You're accidently using an old feature of C that has been deprecated since 1999.
Also, the fact that the link doesn't fail simply means that the standard C library is linked in by default. Whether or not you have included the relevant header is immaterial.
Upvotes: 0
Reputation: 182619
The printf
function is in the C library (libc
in your case) which is linked implicitly (actually gcc has a printf builtin but it's outside the point).
Including the header doesn't bring in any functions for the linker, it simply informs the compiler about their declarations (i.e. "what they look like").
Obviously you should always include headers otherwise you force the compiler into making assumptions about what the functions look like.
Upvotes: 7