两个格式说明符但只有一个参数[关闭]

问题描述 投票:-6回答:3
#include<stdio.h>
int main() {
    int j=65;
    printf("j>=65?%d:%c\n",j);
    return 0;
}

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

c printf output conditional-operator format-specifiers
3个回答
0
投票

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

来自standard

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

强调我的。


1
投票

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

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

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

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


0
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.