Why is #include <stdio.h> not required to use printf()?
c, declaration, include, printf
Solution
In strict compliance mode (that means "in theory"), you invoke undefined behaviour (which is bad) when you call a function that takes a variable number of arguments without a prototype declaration of the function in scope. That means that the compiler is allowed to do anything it likes with a program that uses `printf()` without the prototype from `#include <stdio.h>` or an equivalent declaration. "Anything it likes" includes working correctly as one of the options; that seems to be the option chosen by your example.
In practice, the code will work OK with most practical compilers even without the formal declaration of the `printf()` function.
As was pointed out by qrdl, the function was found because the C compiler links with the C library.
Note that Chris Young's comment about C99 and 'implicit int' is accurate, but the rule about 'variable arguments functions must have a prototype in scope' applies to both C89 and C99. Most compilers do not work in a strict C99 compatibility mode by default because there is too much code that would not compile like that.
Chris Young commented:
To clarify, my comment was on C99 removing implicit declarations. By saying "implicit int", I think you are referring to the C89 feature of allowing declarations such as foo(void); to mean int foo(void);, something C99 also removed.
Chris is, of course, correct. There were two 'implicit declaration' features removed from the C99 standard. The foreword to the standard lists them as:
- remove implicit `int`
- remove implicit function declaration
I was not thinking (and hence not writing) clearly enough. Nevertheless, both C89 and C99 require a prototype in scope for functions that take a variable number of arguments.
To illustrate:
extern int pqr();
int main(void)
{
int i = pqr(1, 3);
return i;
}
Without the first line, this is a correct C89 fragment with an implicit declaration of the function `pqr()` as a function that returns an integer (with unspecified arguments). If the first line is replaced by `extern pqr();`, then this is a correct C89 fragment with an explicit declaration of `pqr()` as a function that returns an integer (with unspecified arguments), but the return type is 'implicit `int`'. As written, the function is explicitly declared and has an explicit `int` return type - but it still has unspecified arguments. I believe that is valid C99 - albeit not wholly desirable. Certainly, GCC (3.4.4) accepts it with the options '`-std=c99 -pedantic`". Ideally, the function declaration should include the full prototype. (And, if `pqr()` were defined with ellipsis, that prototype would be required in theory!)
Problem
Session transcript: ``` > type lookma.c int main() { printf("%s", "no stdio.h"); } > cl lookma.c Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. lookma.c Microsoft (R) Incremental Linker Version 8.00.50727.762 Copyright (C) Microsoft Corporation. All rights reserved. /out:lookma.exe lookma.obj > lookma no stdio.h ```