Vikram
Vikram

Reputation: 2069

C program without header

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

Answers (5)

John Bode
John Bode

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:

  1. 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;

  2. 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).


  1. I say "usually"; I've run across some headers that contained code, but those were usually written by people who didn't know what they were doing. There may be very rare occasions where putting code in a header is justified, but as a rule it's bad practice.

Upvotes: 1

ouah
ouah

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

Jon Purdy
Jon Purdy

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

NPE
NPE

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

cnicutar
cnicutar

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

Related Questions