c: 将 char 值类型转换为 unsigned short

c: type casting char values into unsigned short

从一段伪代码开始:

char a = 0x80;
unsigned short b;
b = (unsigned short)a;
printf ("0x%04x\r\n", b); // => 0xff80

根据我目前的理解,"char" 根据定义既不是 signed char 也不是 unsigned char,而是第三种类型的符号。

为什么 'a' 首先从(可能取决于平台)8 位存储符号扩展到(可能又是特定于平台的)16 位有符号短整数,然后转换为一个未签名的短?

有没有一个c标准决定展开的顺序?

本标准指南是否以任何方式处理 "pure" 字符的第三种类型的符号(我曾称它为 X-char,x 表示未确定的符号),以便结果位于确定性最低?

PS:如果在赋值行的'a'前插入一个“(unsigned char)”语句,那么打印行的结果确实变成了0x0080。因此,只有连续两次类型转换才能提供某些意图的预期结果。

类型 char 不是 "third" 符号。它是 signed charunsigned char,具体是哪一个由实现定义。

这是由 C standard 的第 6.2.5p15 节规定的:

The three types char , signed char , and unsigned char are collectively called the character types. The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char.

看来在您的实现中,charsigned char 相同,因此因为该值为负数并且因为目标类型是无符号的,所以必须对其进行转换。

第 6.3.1.3 节规定了整数类型之间的转换是如何发生的:

1 When a value with integer type is converted to another integer type other than _Bool ,if the value can be represented by the new type, it is unchanged.

2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

由于值 0x80 == -128 无法在 unsigned short 中表示,因此发生第 2 段中的转换。

char 具有实现定义的签名。它要么是有符号的,要么是无符号的,具体取决于编译器。在某种程度上,char 确实是第三种字符类型,请参阅 char 具有不确定的(不可移植的)符号,因此绝不能用于存储原始数字。

但在这种情况下这并不重要。

  • 在您的编译器上,char 已签名。
  • char a = 0x80; 以特定于编译器的方式强制从 0x80 类型(即 int)转换为 char。通常在 2 的补码系统上,这意味着 char 获得值 -128,这里似乎就是这种情况。
  • b = (unsigned short)a; 强制从 char 转换为 unsigned short 1)。 C17 6.3.1.3 有符号和无符号整数然后说:

    Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

    比最大值多一个 65536。所以你可以把它想象成 -128 + 65536 = 65408.

  • 65408的无符号十六进制表示是0xFF80。任何地方都没有符号扩展!


1) 不需要强制转换。当 = 的两个操作数都是算术类型时,如本例所示,右操作数将隐式转换为右操作数的类型 (C17 6.5.16.1 §2)。