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

时间:2017-12-24 17:18:21

标签: c printf output conditional-operator format-specifiers

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

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

3 个答案:

答案 0 :(得分:1)

您将双引号放在错误的位置:引用整个表达式,而不是使您的格式字符串成为条件:

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

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

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

答案 1 :(得分:0)

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

更长的答案是旧的编译器没有检查printf字符串与传递的参数,因此默认情况下编译器不会将此视为错误。如果您启用了正确的警告(-Wformat),它将在编译时抱怨此问题,并且-Werror警告将升级为错误。因为在编译时不会检查它,所以需要从调用堆栈中的应用位置获取所需的参数。这意味着在最后一个指定参数之后的第一个参数可能与堆栈帧的返回地址有关,但在此之后您开始进入未分配的内存。无论哪种方式,行为都是未定义的。

如果您对更多细节感兴趣,stack overflow answer可以解释它。

答案 2 :(得分:0)

这足以让我解释你所展示的一切。你看到的行为可以是任何未定义的行为。

来自standard

  

fprintf函数将输出写入stream指向的流,   在格式指向的字符串的控制下,指定如何   后续参数将转换为输出。 如果有的话   对于格式的参数不足,行为未定义。

强调我的