繁体   English   中英

Tilde C unsigned vs signed integer

[英]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

更多信息请访问:

http://en.wikipedia.org/wiki/Two%27s_complement

unsigned int i  = ~0;

结果:我可以分配给i的最大数量

通常,但不一定。 表达式~0评估为具有所有(非填充)位的int C标准允许对有符号整数进行三次表示,

  • 二进制补码,在这种情况下~0 = -1并将其赋值给unsigned int结果为(-1) + (UINT_MAX + 1) = UINT_MAX
  • 一个补码,在这种情况下, ~0可以是负零或陷阱表示; 如果它是负零,则对unsigned int的赋值将导致0。
  • 签和幅度,在这种情况下~0INT_MIN == -INT_MAX ,并将其分配给一个unsigned int在结果(UINT_MAX + 1) - INT_MAX ,这是1 ,所述较少的情况下unsigned int的宽度(数无符号整数类型的值位数,值位数+ 1 [对于符号位]对于有符号整数类型)小于int2^(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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM