【问题标题】:Defined behavior, passing character to printf("%02X"定义的行为,将字符传递给 printf("%02X"
【发布时间】:2011-05-20 08:14:43
【问题描述】:

我最近遇到this question,其中 OP 在打印变量的十六进制值时遇到问题。我相信问题可以通过following code来总结:

#include <stdio.h>

int main() {
    char signedChar = 0xf0;

    printf("Signed\n”);
    printf(“Raw: %02X\n”, signedChar);
    printf(“Masked: %02X\n”, signedChar &0xff);
    printf(“Cast: %02X\n", (unsigned char)signedChar);

    return 0;
}

这给出了以下输出:

Signed
Raw: FFFFFFF0
Masked: F0
Cast: F0

用于每个打印的格式字符串是%02X,我一直将其解释为“将提供的int 打印为至少两位数字的十六进制值”。

第一种情况将signedCharacter作为参数传递并打印出错误的值(因为int的其他三个字节都设置了它们的所有位)。

第二种情况解决了这个问题,通过对值应用位掩码 (0xFF) 来删除除最低有效字节之外的所有字节,其中存储了char。这应该工作吗?确定:signedChar == signedChar &amp; 0xFF?

第三种情况通过将字符转换为unsigned char 来解决问题(这似乎清除了前三个字节?)。

对于上述三种情况,谁能告诉我行为是否已定义?如何/在哪里?

【问题讨论】:

  • 小于 int 的整数类型在传递给 printf 时被提升为 int。
  • 由于 C 标准中没有定义数字的底层位表示,因此未指定确切的输出。
  • @Paul R:那么在第二种情况下,提升总是在应用位掩码之前进行吗?或者它会在面具没有效果之后发生吗?
  • char 的签名是实现定义的,顺便说一下。如果您想要签名字符,请使用signed char。
  • @unwind:真的吗?我一直假设变量是默认签名的,除非您另有说明。整数也一样吗?

标签: c printf undefined


【解决方案1】:

我不认为这种行为完全由 c 标准定义。毕竟它取决于有符号值的二进制表示。我只会描述它是如何工作的。

printf(“Raw: %02X\n”, signedChar);

(char)0xf0 可以写成(char)-16 转换为(int)-16 其十六进制表示为0xfffffff0。

printf(“Masked: %02X\n”, signedChar &0xff);

0xff 的类型为 int,因此在计算 &amp; 之前,signedChar 被转换为 (int)-16。 ((int)-16) &amp; ((int)0xff) == (int)0x000000f0.

printf(“Cast: %02X\n", (unsigned char)signedChar);

(unsigned char)0xf0 可以写成(unsigned char)240 转换为(unsigned int)240 十六进制是0x000000f0

【讨论】:

  • (unsigned char)240 按照 C99 标准中的 6.3.1.1:2 转换为 (int)240:“如果 int 可以表示原始类型的所有值,则该值将转换为 int”
  • 如果我只想打印 2 个符号,哪种方式更好/更快?蒙面还是演员?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 2019-09-27
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
  • 2013-03-17
  • 1970-01-01
相关资源
最近更新 更多