两个格式说明符但只有一个参数

Two format specifiers but only one argument

#include<stdio.h>
int main() {
    int j=65;
    printf("j>=65?%d:%c\n",j);
    return 0;
}

好的,据了解代替 %d,将打印 j 的值,但为什么 %cö 替换,我无法理解该程序的输出,请解释printf 语句。

对此的简短回答是,这是未定义的行为,打印的字符可以是任何字符,程序甚至可能崩溃。

较长的答案是旧的编译器不会根据传递的参数检查 printf 字符串,因此默认情况下编译器不会将此视为错误。如果您启用正确的警告 (-Wformat),它会在编译时抱怨这一点,而对于 -Werror,警告将升级为错误。因为这在编译时没有检查,所以从它们应该在调用堆栈上的位置获取所需的尽可能多的参数。这意味着最后一个指定参数之后的第一个参数可能与堆栈帧的 return 地址或其他东西有关,但在那之后你开始推入未分配的内存。无论哪种方式,行为都是未定义的。

如果您对更多细节感兴趣,stack overflow answer 解释得很好。

你把双引号放在了错误的地方:你引用了整个表达式,而不是让你的格式字符串成为条件字符串:

printf((j >= 65 ? "%d\n" : "%c\n"), j);

您的 j >= 65 ? ... : ... 表达式是字符串文字的一部分。 C 编译器不会 "see" 将其视为与 j 相关的任何内容。因此,格式字符串包含两个格式说明符和一个打印项;那是未定义的行为。

UB 以不同的方式表现出来;在您的特定系统上,打印了一个垃圾字符 'ö'。但是,这不是保证的行为 - 在其他系统上您可能会得到不同的输出或崩溃。请参阅 this Q&A 了解 UB 的解释。

我想这足以解释您所展示的内容。您看到的行为可以是任何未定义的行为。

来自 standard

The fprintf function writes output to the stream pointed to by stream, under control of the string pointed to by format that specifies how subsequent arguments are converted for output. If there are insufficient arguments for the format, the behavior is undefined.

强调我的