chqrlie chqrlie - 3 months ago 9
C Question

Does calling printf without a proper prototype invoke undefined behavior?

Does this innocent looking program invoke undefined behavior:

int main(void) {
printf("%d\n", 1);
return 0;
}

Answer

Yes invoking printf() without a proper prototype (from the standard header <stdio.h> or from a properly written declaration) invokes undefined behavior.

As documented in C11 Annex J (informative only)

J2 Undefined Behavior

  • For call to a function without a function prototype in scope where the function is defined with a function prototype, either the prototype ends with an ellipsis or the types of the arguments after promotion are not compatible with the types of the parameters (6.5.2.2).

This annex is not normative, but clearly documents the above code as an example of undefined behavior.

In more pragmatic words, in the absence of a prototype for printf, the compiler generates the calling sequence as if printf was defined as int printf(const char*, int) which may be quite different and incompatible with the actual implementation of printf in the standard library, defined as int printf(const char restrict *format, ...).

Ancient ABIs were regular enough that this would not cause a problem, but modern (eg 64-bit) ABIs use more efficient calling sequences that make the above code definitely incorrect.

As a consequence, this famous classic C program would fail too, without the #include <stdio.h> or at least a proper prototype for printf:

int main(void) {
    printf("Hello world\n");  // undefined behavior
    return 0;
}