【问题标题】:C++ casting char into shortC ++将char转换为short
【发布时间】:2022-01-14 06:18:54
【问题描述】:

请原谅我这个新手问题。我最近在将 char 转换为 short 时发现了一件奇怪的事情。基本上,如果字符溢出,当转换成short时,二进制数会在前面加上11111111。如果字符没有溢出,它将在前面加上00000000。

例如,

char a = 130;
short b = (short)a;
printf("%hhx\n", a);
printf("%hx\n", b);

打印

82
ff82

虽然

char a = 125;
short b = (short)a;
printf("%hhx\n", a);
printf("%hx\n", b);

打印

7d
7d

所以在进行强制转换时,是否在确定将其强制转换为哪个二进制数之前检查变量类型和值(决定 b/w 前置 0xFF 还是 0x00)?这背后有什么原因吗?似乎总是做(short)a & 0x00FF 会是一个好习惯吗?

【问题讨论】:

  • 您只是看到了有符号值扩展的机制。
  • 两个(不相关的)问题:1)如果您觉得需要在 C++ 中进行 C 风格的转换(如 (short)a),那么您应该将其视为您正在做的标志有事吗; 2) 为什么在 C++ 代码中使用printf
  • 与您的问题更相关的是,如果char 是有符号或无符号的,它是特定于实现的(即取决于编译器)。
  • 代码中的演员表无关;编译器会在没有被明确告知的情况下进行转换。
  • 进行位处理时的良好做法是使用名称中指示位的类型。例如 uint16_t 代替 short 或 int8_t 代替 char。这些使代码读者更清楚逻辑依赖于精确的位。包含 以获得这些类型。

标签: c++ casting char type-conversion short


【解决方案1】:

阅读:2's complement,了解负数如何以二进制编码。

signed char 中,假设 8 位字符宽度和 2 的补码拱形,一个字符可以保存 -128 到 +127 之间的值。

当你说:

char a = 130;

超出范围。

130 作为 32 位二进制整数是:00000000 00000000 00000000 10000010

在十六进制中,它是:00 00 00 82。这就是您的82 值的来源。

int(130) 被强制转换为 char 时,它基本上只是被最后一个字节的位截断:10000010

因此 char a = <binary:10000010> 在 2 的补码算术中是 -126

因此,当您分配 short b = a 时,您只是被分配了 -126 给一个短路。

在 2 的补码体系结构中,当负数提升为更大的类型时,它会得到“符号扩展”。也就是说,如果带符号字符的最高有效位是1,那么当它被转换为短字符时,额外的字节也会以1s 开头。即-126作为16位二进制是:11111111 100000100xff82

尝试将a 声明为unsigned char,您应该会得到不同的结果。

【讨论】:

  • 谢谢!是的,我知道 2 的补码。正如您所指出的,我不知道的是基于检查无符号字符的最重要位的“符号扩展”。
【解决方案2】:
char a = 130;

char 在您的系统上很有可能是 8 位,我们可以根据输出猜测它是有符号类型。在这种情况下,char 的最大可表示值是 127。130 大于 127,因此无法表示。在这种情况下,转换后的值将是与 130 模 128 一致的可表示值,即 -126。当您转换为两个字节short 时,该值保持不变-126。 ff82 是如何将 -126 表示为两个字节的二进制补码数。

似乎总是做 (short)a & 0x00FF 会是一个好习惯吗?

如果您这样做了,那么 b 的值将不同于 (130) 与 a 的值 (-126)。获得一个结果而不是另一个结果是一种“好习惯”吗?这取决于您需要哪种结果。

位掩码仅对无符号类型才真正有意义。

为有符号整数类型分配不可表示的值很少有意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    • 2015-01-20
    • 2017-08-17
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    相关资源
    最近更新 更多