【问题标题】:Please explain the difference in the printfs below请解释下面printfs的区别
【发布时间】:2016-04-28 08:30:22
【问题描述】:
printf("%x\n",(const uint8_t *)0x0D);
printf("%x\n",(const uint8_t)0x0D);
printf("%x\n",(uint8_t *)0x0D);
printf("%x\n",0x0D);

他们都给我D。这里const*s有什么意义?

【问题讨论】:

  • 把编译器的警告调到最大,你就会发现这段代码出了什么问题。
  • 那些有指针转换的都是错误的。这是主要区别。使用-Wall 选项编译您的代码。 GCC 将为您提供所有信息。
  • 这些都不正确。最后一个应该有后缀U,因为x 需要一个无符号类型。但 0x0D 已签名。
  • @2501 OP 的代码在第 4 行是正确的。请参阅 C11 §6.5.2.2 11. 当传递的 ... 值在 intunsigned 范围内时,没有区别。

标签: c printf format-specifiers


【解决方案1】:

%x 格式说明符将参数指定为unsigned int 类型。

在你的情况下,

 printf("%x\n",(const uint8_t)0x0D);
 printf("%x\n",0x0D);

参数将被提升(默认提升规则)以匹配类型,但如果是

 printf("%x\n",(const uint8_t *)0x0D);  //supplying a pointer
 printf("%x\n",(uint8_t *)0x0D);        //supplying a pointer

您将根据C11,第 7.21.6.1 章调用 undefined behavior

[...] 如果有任何参数 不是相应转换规范的正确类型,行为是 不明确的。 [...]

【讨论】:

  • 参数将被提升(默认提升规则)以匹配类型 这是不正确的。在第一个 printf 中,常量在强制转换之后被提升为 int,它与说明符 x 不匹配,而在第二个中,常量的类型已经是 int,它也不匹配 x。您引用的标准部分解释了为什么这些示例是 ub。
  • @2501 第一个是无符号类型,为什么不行?
  • @fluter 因为它被提升为int,使用默认参数提升。
  • @2501 对于这种特殊情况,它可能还不是 UB。当标准描述默认参数提升时,有一个关于有符号和无符号类型的例外:".. 行为未定义,但以下情况除外: — 一个提升类型是有符号整数类型,另一个提升类型是对应的无符号整数类型,并且值在两种类型中都可以表示;".在这种情况下,0x0D 可以在这两种类型中表示。
  • @2501 C11 §6.5.2.2 6 在这里适用
【解决方案2】:

%xprintf 中指定用于将无符号整数参数打印为十六进制表示法。这就是为什么您会看到所有打印“D”的原因。但只有第 4 种形式是正确的。

printf("%x\n",(const uint8_t *)0x0D); // undefined behavior, converting integer constant to a pointer
printf("%x\n",(const uint8_t)0x0D);  // ok, but not necessary
printf("%x\n",(uint8_t *)0x0D); // undefined behavior
printf("%x\n",0x0D); // ok

注意这个函数在任何情况下都不需要常量,所以const根本没用,注意C中的const不做常量,它只定义了只读的东西。

【讨论】:

  • 实现定义?你能引用一些东西吗?
  • @SouravGhosh 谢谢提醒,是UB,我只是想转换,不是printf的期望。
  • 哦,我的错 :-)
  • 第二个也是最后一个 printf 不行。请参阅我对其他答案的评论。
猜你喜欢
  • 2013-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-04
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
相关资源
最近更新 更多