doltes
doltes

Reputation: 313

Why doesn't gcc throw an error when the `printf` function hasn't been defined?

The context

Consider the following file

$ cat main.c
int main() {
  printf("%d", 10);
  return 0;
}

If we stop the compiler after the preprocessor stage, we get

$ gcc -E main.c
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "main.c"
int main() {
  printf("%d", 10);
  return 0;
}

As seen above, the printf function is not defined. However, gcc dooesn't throw a compilation error (see below) when we try to compile the source file shown above

$ gcc main.c 2>/dev/null && echo $?
0

Additional context

I know that gcc warns about this

$ gcc -Wall main.c
main.c: In function ‘main’:
main.c:2:3: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
    2 |   printf("%d", 10);
      |   ^~~~~~
main.c:2:3: warning: incompatible implicit declaration of built-in function ‘printf’
main.c:1:1: note: include ‘<stdio.h>’ or provide a declaration of ‘printf’
  +++ |+#include <stdio.h>
    1 | int main() {

The questions

  1. Why does gcc compile the source file when the printf function hasn't been defined? Are there files that gcc includes in every file by default?
  2. Assuming that gcc, by default, includes some header files in every file. Is there any way to disable this behavior so that when a function (such as printf) is not found in the preprocessor output, an error is thrown instead of a warning?

Upvotes: 0

Views: 530

Answers (2)

James K. Lowden
James K. Lowden

Reputation: 7837

Why does gcc compile the source file when the printf function hasn't been defined?

To be just a bit pedantic, printf isn't declared. The definition of printf -- the object code -- is in the C standard library.

The declaration you're looking for is probably a function prototype. That declares not only the function's name, but its return type and parameters.

When C was invented and first standardized, there were no function prototypes. Machines were small and men were men. You were expected to call your functions correctly, and you did. You didn't want to waste time waiting for the compiler to verify what you obviously were doing correctly.

It didn't always work out that way, sadly. When C was young, on many systems the only memory was real memory, some of which was mapped to the video display. Our home-grown display manager had functions to display and clear dialogs, and/or the whole screen. Different functions written by different people at different times chose a different order for the {address, length} pair of parameters for these functions. The first sign that you'd called one using the wrong argument order was the display being corrupted, at which point often the only recovery was the power switch.

Function prototypes would have helped....

If your compiler is compiling according to that first standard, C89, your code is absolutely correct. Later versions of the C standard made function prototypes advisable and then mandatory. You asked about gcc; have a look at the -std command-line option.

Are there files that gcc includes in every file by default?

Not so as you'd notice. If you're using a function from the C standard library, you'll want to include the header file that goes with it. The man page always says which one that is.

Upvotes: 0

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215287

Indeed, attempting to call the function without a declaration is a constraint violation and thus requires a diagnostic (warning or error) per the C language spec. But a diagnostic is not required to be fatal, and the compiler is permitted to do whatever it likes if it proceeds.

For historical reasons, "implicit function declarations" are allowed by GCC by default; you can change this with -Werror=implicit-function-declaration. However, it's not practical to fix this default or even use this default yourself, thanks to autoconf brokenness: a huge number of autoconf tests probe for existence of functions using test programs that intentionally (for utterly wrong reasons, not even historically valid ones) omit the declaration. So if you changed the default here, autoconf as used in lots of applications would suddenly decide none of the functions it's probing for exist.

Upvotes: 3

Related Questions