在C中没有参数的printf()编译好.怎么样?

Des*_*tor 7 c printf undefined-behavior

我尝试了下面的c程序,我希望得到编译时错误,但为什么编译器没有给出任何错误?

#include <stdio.h>
int main(void)
{
    printf("%d\n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么输出依赖于编译器?这是各种编译器的输出

Orwell Dev C++ IDE上的输出(使用gcc 4.8.1):0

Visual Studio 2010提供的Visual C++输出:0

CodeBlocks IDE(使用gcc 4.7.1):垃圾值

在线编译ideone.com:垃圾值

这里出了什么问题?

Sou*_*osh 9

您的程序将编译正常,printf()可变参数函数和默认情况下不会执行与提供的参数的格式说明符数量的匹配检查.

在运行时,程序显示未定义的行为,因为没有提供必须使用提供的格式说明符打印的参数.

根据章节7.19.6.1,c99标准,(来自fprintf())

如果格式的参数不足,则行为未定义.

如果使用-Wformatflag in gcc编译,则编译器将生成不匹配的警告.


zne*_*eak 6

由于C变量参数的工作原理,编译器无法跟踪它们的正确用法.提供函数需要的较少或更多参数仍然是(语法上)合法的,尽管在查看标准时这通常最终会成为未定义的行为.

声明printf如下:

int printf(const char*, ...);
Run Code Online (Sandbox Code Playgroud)

编译器只能看到...,并且知道该函数可能有或可能没有使用零个或多个其他参数.被调用的函数不知道它传递了多少个参数; 它充其量只能假设它传递了所需的所有信息,仅此而已.

将其与其他语言(如C#)进行对比:

void WriteLine(string format, params object[] arguments);
Run Code Online (Sandbox Code Playgroud)

这里,该方法确切地知道传递了多少额外的参数(做arguments.Length).

在C中,可变函数尤其printf是安全漏洞的常见原因.Printf最终从堆栈中读取原始字节,这可能会泄漏有关应用程序及其安全环境的重要细节.

因此,Clang和GCC支持验证printf格式的特殊扩展.如果使用无效的格式字符串,则会收到警告(而不是错误).

code.c:4:11: warning: more '%' conversions than data arguments [-Wformat]
    printf("%d\n");
           ~~^
Run Code Online (Sandbox Code Playgroud)