【问题标题】:Two format specifiers but only one argument [closed]两个格式说明符,但只有一个参数 [关闭]
【发布时间】:2018-06-06 08:27:17
【问题描述】:
#include<stdio.h>
int main() {
    int j=65;
    printf("j>=65?%d:%c\n",j);
    return 0;
}

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

【问题讨论】:

  • %c 用于在 C 中打印一个字符。查看以下链接以了解如何格式化输出:codingunit.com/…
  • BTW 您的程序完全错误。 充满了undefined behavior 以及编译时间和运行时间之间的混淆。 非常scared。请记住,遗憾的是,C 不是 homoiconic
  • 两个格式说明符,但只有一个参数。
  • 从标准 fprintf 函数将输出写入 stream 指向的流,在 format 指向的字符串的控制下,指定后续参数如何转换为输出。 如果格式的参数不足,则行为未定义。
  • 在提问之前考虑阅读教程。这些信息不难找到。

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


【解决方案1】:

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

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

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

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

【讨论】:

  • 问的问题和我上面输入的类似,我没有创新这个问题,所以请你解释一下我问的问题
  • @user9121710 请在 UB 上查看编辑和问答链接。
【解决方案2】:

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

来自standard

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

强调我的

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 编译器不需要检查格式字符串。即使对于现代编译器,如果没有适当增强的标准头文件,这也是不可能的。即使两者都提供此功能,也不能保证,因为必要的编译器扩展不是标准的一部分(术语“扩展”暗示了这一点)并且支持一个编译器的库可能不支持不同的编译器。
    猜你喜欢
    • 2011-12-28
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多