以伪代码段开头:
numpy
根据我目前的理解,“ char”从定义上来说既不是带符号的字符也不是未签名的字符,而是某种第三种签名。
怎么会发生这样的情况:首先将“ a”符号从一个8位存储(可能与平台有关)扩展到一个16位带符号的short,然后转换为一个无符号的short?
是否有确定扩展顺序的c标准?
该标准指南是否以任何方式处理“纯”字符(我称其为X字符,x表示不确定的字符)的第三种类型的签名,以使结果至少具有确定性? / p>
PS:如果在赋值行的'a'前面插入“(unsigned char)”语句,则打印行的结果确实变为0x0080。因此,连续只有两种类型的强制转换将提供某些意图的预期结果。
答案 0 :(得分:4)
类型char
不是“第三”签名。它是signed char
或unsigned char
,它是实现定义的那个。
这由C standard的6.2.5p15节规定:
三种类型
char
,signed char
和unsigned char
是 统称为字符类型。实施 应将char
定义为具有相同的范围,表示形式和 行为为signed char
或unsigned char
。
在您的实现中,char
似乎与signed char
相同,因此,由于该值为负,并且由于目标类型是未签名的,因此必须对其进行转换。
第6.3.1.3节规定了整数类型之间如何进行转换:
1 将整数类型的值转换为另一种整数类型时 以外 _Bool,如果该值可以用新类型表示,则它保持不变。
2 否则,如果新类型是未签名的,则值为 通过重复加减乘除 新类型可以表示的最大值 直到该值在新类型的范围内。
3 否则,将对新类型进行签名,并且值不能为 代表其中;结果要么是实现定义的,要么是 会产生一个实现定义的信号。
由于无法在unsigned short
中表示值0x80 == -128,因此发生了第2段中的转换。
答案 1 :(得分:2)
char
具有实现定义的签名。它是签名的还是未签名的,取决于编译器。从某种意义上说,char
是第三种字符类型,请参见this。 char
具有不确定的(不可移植的)签名,因此决不能用于存储原始数字。
但是在这种情况下没关系。
char
已签名。char a = 0x80;
以特定于编译器的方式强制从0x80
的类型int
转换为char
。通常在2的补码系统上,这将意味着char
的值是-128
,就像这里的情况一样。 b = (unsigned short)a;
强制从char
到unsigned short
1)的转换。 C17 6.3.1.3有符号和无符号整数然后说:
否则,如果新类型是无符号的,则通过重复加或 比新类型可以表示的最大值多减去一个 直到该值在新类型的范围内。
比最大值多一个65536
。因此,您可以将其视为-128 + 65536 = 65408
。
65408
的无符号十六进制表示形式为0xFF80
。任何地方都没有扩展标志!
1)不需要强制转换。当=
的两个操作数都是算术类型时,在这种情况下,右操作数将隐式转换为右操作数的类型(C17 6.5.16.1§2)。