没有正确的原型调用printf会调用未定义的行为吗?

这个无辜的程序是否会调用未定义的行为:

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

是调用printf()而没有适当的原型(来自标准头文件或来自正确编写的声明)调用未定义的行为。

如C11附录J中所述(仅供参考)

J2未定义的行为

  • 对于在函数原型定义函数的范围内调用没有函数原型的函数,原型以省略号结束或者升级后的参数类型与参数类型不兼容(6.5.2.2) 。

本附件不是规范性的,但清楚地将上述代码记录为未定义行为的示例。

用更务实的话来说,在没有printf原型的情况下,编译器会生成调用序列,就好像printf被定义为int printf(const char*, int) ,这可能是完全不同的,并且与printf的实际实现不兼容。标准库,定义为int printf(const char restrict *format, ...)

古代ABI足够常规,这不会引起问题,但现代(例如64位)ABI使用更有效的调用序列,使上述代码绝对不正确。

因此,这个着名的经典C程序也会失败,没有#include 或者至少是printf原型:

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