首先,您不需要演员表:a
的值隐式转换为unsigned int
,分配为b
。所以,你的语句相当于:
unsigned int b = a;
现在,unsigned
整数类型在C和C++的一个重要特性是它们的值总是在范围[0,最大],其中最大为unsigned int
是UINT_MAX
(它的定义见limits.h
)。如果您分配的值不在该范围内,则会将其转换为该范围。因此,如果值为负数,则重复添加UINT_MAX+1
以使其在[0,UINT_MAX
]范围内。对于上面的代码,就好像我们写了:unsigned int b = (UINT_MAX + a) + 1
。这不等于-a
(534)。
请注意,无论底层表示法是二进制补码,1的补码还是符号幅度(或任何其他外来编码),以上都是真实的。人们可以看到的东西,如:
signed char c = -1;
unsigned int u = c;
printf("%u\n", u);
assert(u == UINT_MAX);
在一个典型的补机具有4个字节的int
,c
是0xff
,并u
是0xffffffff
。编译器必须确保将值-1
分配给u
时,它将转换为等于UINT_MAX
的值。
现在回到您的代码中,printf
格式字符串对于b
是错误的。你应该使用%u
。当你这样做时,你会发现它输出的值是UINT_MAX - 534 + 1
而不是534
。
当在比较运算符<
使用,因为b
是unsigned int
,a
也转换为unsigned int
。这与b = a
给出;之前,意味着a < b
为false:a
作为unsigned int
等于b
。
假设你有一个的补机,和你做:
signed char c = -1;
unsigned char uc = c;
比方说,机上的char
(符号或无符号)为8位。然后c
和uc
将存储下列值,位模式:
+----+------+-----------+
| c | -1 | 11111110 |
+----+------+-----------+
| uc | 255 | 11111111 |
+----+------+-----------+
注意的c
和uc
位模式是不一样的。编译器必须确保c
具有价值-1
,并uc
具有价值UCHAR_MAX
,这是255这台机器上。
上有my answer to a question here on SO更多细节。
你可能要检查你的编译器文档和看是否有检查printf格式说明符的选项。 gcc有-Wformat,它会在编译时警告你关于%d和%u的事情。 – 2010-03-01 12:13:19
http://stackoverflow.com/questions/50605/signed-to-unsigned-conversion-in-c-is-it-always-safe – 2016-04-18 17:36:50
这不应该有一个C++标签。 – Friedrich 2017-07-18 23:39:07