【问题标题】:Is printf()'s string width safe with unterminated strings?printf() 的字符串宽度对于未终止的字符串是否安全?
【发布时间】:2016-01-12 16:47:43
【问题描述】:

以下定义是否明确?

const char not_a_c_string[] = { 'h', 'e', 'l', 'l', 'o' };
printf( "%.5s", (const char*) not_a_c_string );

这是一个关于特定形式 "%.5s" 的问题,而不是 如何打印可能不是 NUL 终止的字符串? 因为这个问题有 already been answered here,其中 "%.*s" 构造是建议。

【问题讨论】:

  • 查看 dup 接受的答案。何时确定长度无关紧要。只需使用固定大小。不过,我建议避免使用幻数,要么使用带有 WIDTH 宏的一点宏魔术,要么仍然显式传递长度。
  • YSC,我根据@rici 先生的评论修改了我的答案。如果您真的想了解精度,请edit 提出问题并添加说明以使其完整。谢谢。
  • 我不会撤回我的投票,因为它重复。 RTFM 怎么样? printf 定义明确。请注意,您指定了字段宽度。 proceision 是另一个字段。
  • 很好奇,为什么是(const char*)

标签: c printf language-lawyer undefined-behavior


【解决方案1】:

首先,我相信您的意思是询问精度,而不是字段宽度。所以,你的例子看起来像

 printf( "%.5s", (const char*) not_a_c_string );  //precision

而不是

 printf( "%5s", (const char*) not_a_c_string );   //field width.

考虑到上述方法,不,在您的示例中不会是UB。

引用C11 标准,第 7.21.6.1 章,fprintf 函数,第 8 段,(强调我的

s               如果不存在 l 长度修饰符,则参数应为指向初始值的指针 字符类型数组的元素。(280) 数组中的字符是 写到(但不包括)终止空字符。如果 指定精度,写入的字节数不超过。 如果 精度未指定或大于数组的大小,数组应 包含一个空字符。

所以,只有当你是,你才需要有一个空分隔的数组(string

  • 缺少精度
  • 提供的精度是 > 提供的 char 数组的大小。

在您的情况下,提到的精度 (5) 不大于 数组的大小(也是 5)。所以,没关系。


FWIW,如果示例仍然存在

 printf( "%5s", (const char*) not_a_c_string );

那么它将是 UB,因为你会在那里丢失精度。

【讨论】:

  • @PaulR:我认为您错过了第一句话:“不,在您的示例中它不会是 UB。” (强调我的)他同意你的观点
  • 啊哈 - 我的错 - 全面道歉 - 否决票和 cmets 已删除。
  • @PaulR 感谢您再次访问。我已经更新了答案以消除任何可能的混淆。 :)
  • 提供的格式("%5s"缺少精度,所以肯定是UB。如果是"%.5s",您的答案将适用。首先,5 是“字段宽度”。
  • @PaulOgilvie:Sourav 引用了标准对fprintf 的定义,它清楚地表明在这种情况下,数组必须包含 NUL。由于不满足约束,fprintf 的行为未定义(根据定义)。
猜你喜欢
  • 1970-01-01
  • 2019-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-16
  • 2014-06-09
  • 2014-06-14
相关资源
最近更新 更多