Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
}
like image 233
chqrlie Avatar asked Jul 31 '16 17:07

chqrlie


1 Answers

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 the C Standard:

6.5.2.2 Function calls

  • If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not equal the number of parameters, the behavior is undefined. If the function is defined with a type that includes a prototype, and either the prototype ends with an ellipsis (, ...) or the types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined.

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 could fail too, without the #include <stdio.h> or at least a proper prototype for printf:

int main() {
    printf("Hello world\n");  // undefined behavior
    return 0;
}
like image 147
chqrlie Avatar answered Sep 29 '22 02:09

chqrlie