[英]Tilde C unsigned vs signed integer
例如:
unsigned int i = ~0;
结果 :我可以分配给i
最大数量
和
signed int y = ~0;
结果 : -1
为什么我得到-1
? 我不应该得到我可以分配给y
的最大数量吗?
4294967295
(又名UINT_MAX
)和-1
都具有相同的0xFFFFFFFF
二进制表示或32位全部设置为1
。 这是因为带符号的数字用二进制补码表示。 负数将其MSB(最高有效位)设置为1
并通过翻转其余位来确定其值,加1
并乘以-1
。 因此,如果您将MSB设置为1
并且其余位也设置为1
,则将它们翻转(获得32个零),添加1
(获得1
)并乘以-1
以最终获得-1
。
这使得CPU更容易进行数学计算,因为它不需要负数的特殊例外。 例如,尝试添加0xFFFFFFFF
(-1)和1
。 由于只有32位的空间,这将溢出,结果将如预期的那样为0
。
更多信息请访问:
unsigned int i = ~0;
结果:我可以分配给i的最大数量
通常,但不一定。 表达式~0
评估为具有所有(非填充)位的int
。 C标准允许对有符号整数进行三次表示,
~0 = -1
并将其赋值给unsigned int
结果为(-1) + (UINT_MAX + 1) = UINT_MAX
。 ~0
可以是负零或陷阱表示; 如果它是负零,则对unsigned int
的赋值将导致0。 ~0
是INT_MIN == -INT_MAX
,并将其分配给一个unsigned int
在结果(UINT_MAX + 1) - INT_MAX
,这是1
,所述较少的情况下unsigned int
的宽度(数无符号整数类型的值位数,值位数+ 1 [对于符号位]对于有符号整数类型)小于int
和2^(WIDTH - 1) + 1
在常见情况下, unsigned int
的宽度与int
的宽度相同。 初始化
unsigned int i = ~0u;
将始终导致i
持有值UINT_MAX
。
signed int y = ~0;
结果:-1
如上所述,只有当有符号整数的表示使用二进制补码时(现在这是迄今为止最常见的表示)。
~0
仅仅是一个int
设置为1时解释所有比特作为unsigned
这将等同于UINT_MAX
。 当解释为signed
这将是-1
。
假设32位整数:
0 = 0x00000000 = 0 (signed) = 0 (unsigned)
~0 = 0xffffffff = -1 (signed) = UINT_MAX (unsigned)
保罗的回答是完全正确的。 而不是使用〜0,您可以使用:
#include <limits.h>
signed int y = INT_MAX;
unsigned int x = UINT_MAX;
现在,如果你检查值:
printf("x = %u\ny = %d\n", UINT_MAX, INT_MAX);
您可以在系统上看到最大值。
不,因为~
是按位NOT运算符,而不是类型运算符的最大值 。 ~0
对应一个int
,所有位都设置为1
,解释为unsigned,给出了无符号可表示的最大数,并解释为signed int,给出-1。
你必须使用二进制补机。
查看http://en.wikipedia.org/wiki/Two%27s_complement ,了解一下布尔代数和逻辑设计。 学习如何计算二进制和二进制加法和减法将进一步解释这一点。
C语言使用这种数字形式,以便找到使用0x7FFFFFFF所需的最大数字。 (对于每个使用的字节使用2个FF,最左边的字节是7.)要理解这一点,您需要查找十六进制数字及其工作方式。
现在来解释一下无符号的等价物。 在带符号的数字中,数字的下半部分是负数(0表示为正数,因此负数实际上比正数高1)。 无符号数字都是正数。 因此理论上你的32位int的最高数字是2 ^ 32,除了0仍然被计为正数所以它实际上是2 ^ 32-1,现在对于有符号数字,这些数字的一半是负数。 这意味着我们将前一个数字2 ^ 32除以2,因为32是指数,我们得到每侧2 ^ 31个数字0为正数意味着有符号32位int的范围是(-2 ^ 31,2 ^ 31- 1)。
现在只比较范围:无符号32位int:(0,2 ^ 32-1)有符号32位int:( - 2 ^ 31,2 ^ 32-1)无符号16位int:(0,2 ^ 16-1)签名16位int:( - 2 ^ 15,2 ^ 15-1)
你应该能够看到这里的模式。 解释〜0的事情需要多一点,这与二进制中的减法有关。 它只是添加1并翻转所有位然后将两个数字相加。 C在幕后为您完成此操作,许多处理器也是如此(包括x86和x64系列处理器)。因此,最好存储负数,就像它们倒计时一样,并且在二进制补码中,添加的1也被隐藏。 因为0被假定为正,因此负数不能具有0的值,因此它们自动地将-1(位翻转后的正1)添加到它们。 在解码负数时,我们必须考虑到这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.