C++ 将 char 转换为 short

C++ casting char into short

请原谅我这个新手问题。我最近发现将 char 转换为 short 时有一件奇怪的事情。基本上,如果 char 溢出,当转换为 short 时,二进制数前面加上 11111111。如果 char 没有溢出,它将加上 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 是个好习惯?

char a = 130;

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

It seems always doing (short)a & 0x00FF would be a good practice?

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

位掩码只对无符号类型有意义。

将无法表示的值分配给有符号整数类型很少有意义。

继续阅读: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 的补码架构中,当负数被提升为更大的类型时,它会被“符号扩展”。也就是说,如果 signed char 的最高有效位是 1,那么当它被转换为 short 时,额外的字节也会以 1 开头。也就是说,-126 作为 16 位二进制是:11111111 100000100xff82

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