C++ 为什么 unsigned int 0xFFFFFFFF 等于 int -1?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1863153/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why unsigned int 0xFFFFFFFF is equal to int -1?
提问by conejoroy
In C or C++ it is said that the maximum number a size_t (an unsigned int data type) can hold is the same as casting -1 to that data type. for example see Invalid Value for size_t
在 C 或 C++ 中,据说 size_t(无符号 int 数据类型)可以容纳的最大数量与将 -1 转换为该数据类型相同。例如,请参阅size_t 的无效值
Why?
为什么?
I mean, (talking about 32 bit ints) AFAIK the most significant bit holds the sign in a signed data type (that is, bit 0x80000000 to form a negative number). then, 1 is 0x00000001.. 0x7FFFFFFFF is the greatest positive number a int data type can hold.
我的意思是,(谈论 32 位整数)AFAIK 最高有效位保存有符号数据类型的符号(即位 0x80000000 以形成负数)。那么,1 是 0x00000001.. 0x7FFFFFFFF 是 int 数据类型可以容纳的最大正数。
Then, AFAIK the binary representation of -1 int should be 0x80000001 (perhaps I'm wrong). why/how this binary value is converted to anything completely different (0xFFFFFFFF) when casting ints to unsigned?? or.. how is it possible to form a binary -1 out of 0xFFFFFFFF?
然后,AFAIK -1 int 的二进制表示应该是 0x80000001 (也许我错了)。为什么/如何在将整数转换为无符号时将这个二进制值转换为完全不同的(0xFFFFFFFF)?或者..如何从0xFFFFFFFF中形成二进制-1?
I have no doubt that in C: ((unsigned int)-1) == 0xFFFFFFFF or ((int)0xFFFFFFFF) == -1 is equally true than 1 + 1 == 2, I'm just wondering why.
我毫不怀疑,在 C: ((unsigned int)-1) == 0xFFFFFFFF 或 ((int)0xFFFFFFFF) == -1 与 1 + 1 == 2 同样正确,我只是想知道为什么。
回答by Alok Singhal
C and C++ can run on many different architectures, and machine types. Consequently, they can have different representations of numbers: Two's complement, and Ones' complement being the most common. In general you should not rely on a particular representation in your program.
C 和 C++ 可以在许多不同的体系结构和机器类型上运行。因此,它们可以有不同的数字表示形式:二的补码和一的补码是最常见的。通常,您不应依赖程序中的特定表示。
For unsigned integer types (size_t
being one of those), the C standard (and the C++ standard too, I think) specifies precise overflow rules. In short, if SIZE_MAX
is the maximum value of the type size_t
, then the expression
对于无符号整数类型(size_t
是其中之一),C 标准(我认为也是 C++ 标准)指定了精确的溢出规则。简而言之,如果SIZE_MAX
是 type 的最大值size_t
,则表达式
(size_t) (SIZE_MAX + 1)
(size_t) (SIZE_MAX + 1)
is guaranteed to be 0
, and therefore, you can be sure that (size_t) -1
is equal to SIZE_MAX
. The same holds true for other unsigned types.
保证为0
,因此,您可以确定(size_t) -1
等于SIZE_MAX
。这同样适用于其他无符号类型。
Note that the above holds true:
请注意,上述情况成立:
- for all unsigned types,
- even if the underlying machine doesn't represent numbers in Two's complement. In this case, the compiler has to make sure the identity holds true.
- 对于所有无符号类型,
- 即使底层机器不表示 Two's补码中的数字。在这种情况下,编译器必须确保身份成立。
Also, the above means that you can't rely on specific representations for signedtypes.
此外,以上意味着您不能依赖签名类型的特定表示。
Edit: In order to answer some of the comments:
编辑:为了回答一些评论:
Let's say we have a code snippet like:
假设我们有一个代码片段,如:
int i = -1;
long j = i;
There is a type conversion in the assignment to j
. Assuming that int
and long
have different sizes (most [all?] 64-bit systems), the bit-patterns at memory locations for i
and j
are going to be different, because they have different sizes. The compiler makes sure that the valuesof i
and j
are -1
.
在对 的赋值中有一个类型转换j
。假设int
和long
具有不同的大小(大多数[全部?] 64 位系统),i
和 的内存位置的位模式j
将不同,因为它们具有不同的大小。编译器可以确保值的i
和j
是-1
。
Similarly, when we do:
同样,当我们这样做时:
size_t s = (size_t) -1
There is a type conversion going on. The -1
is of type int
. It has a bit-pattern, but that is irrelevant for this example because when the conversion to size_t
takes place due to the cast, the compiler will translate the valueaccording to the rules for the type (size_t
in this case). Thus, even if int
and size_t
have different sizes, the standard guarantees that the value stored in s
above will be the maximum value that size_t
can take.
正在进行类型转换。该-1
是类型int
。它有一个位模式,但这与本示例无关,因为当转换为size_t
由于强制转换而发生时,编译器将根据类型规则(在本例中)转换值size_t
。因此,即使int
和size_t
具有不同的大小,标准保证s
上面存储的值将是size_t
可以取的最大值。
If we do:
如果我们这样做:
long j = LONG_MAX;
int i = j;
If LONG_MAX
is greater than INT_MAX
, then the value in i
is implementation-defined (C89, section 3.2.1.2).
如果LONG_MAX
大于INT_MAX
,则中的值i
是实现定义的(C89,第 3.2.1.2 节)。
回答by Mark Ransom
It's called two's complement. To make a negative number, invert all the bits then add 1. So to convert 1 to -1, invert it to 0xFFFFFFFE, then add 1 to make 0xFFFFFFFF.
它被称为二进制补码。要生成负数,请反转所有位,然后加 1。因此,要将 1 转换为 -1,将其反转为 0xFFFFFFFE,然后加 1 以生成 0xFFFFFFFF。
As to why it's done this way, Wikipediasays:
至于为什么这样做,维基百科说:
The two's-complement system has the advantage of not requiring that the addition and subtraction circuitry examine the signs of the operands to determine whether to add or subtract. This property makes the system both simpler to implement and capable of easily handling higher precision arithmetic.
二进制补码系统的优点是不需要加法和减法电路检查操作数的符号来确定是加还是减。此属性使系统既易于实现又能够轻松处理更高精度的算术。
回答by Jerry Coffin
Your first question, about why (unsigned)-1
gives the largest possible unsigned value is only accidentally related to two's complement. The reason -1 cast to an unsigned type gives the largest value possible for that type is because the standard says the unsigned types "follow the laws of arithmetic modulo 2nwhere n is the number of bits in the value representation of that particular size of integer."
你的第一个问题,关于为什么(unsigned)-1
给出最大可能的无符号值只是偶然地与二进制补码相关。将 -1 强制转换为无符号类型的原因给出了该类型可能的最大值是因为标准说无符号类型“遵循算术模 2 n的法则,其中 n 是该特定大小的值表示中的位数整数。”
Now, for 2's complement, the representation of the largest possible unsigned value and -1 happen to be the same -- but even if the hardware uses another representation (e.g. 1's complement or sign/magnitude), converting -1 to an unsigned type must still produce the largest possible value for that type.
现在,对于 2 的补码,最大可能的无符号值和 -1 的表示恰好相同——但即使硬件使用另一种表示(例如 1 的补码或符号/幅度),也必须将 -1 转换为无符号类型仍然为该类型产生最大的可能值。
回答by pmg
Two's complementis very nice for doing subtraction just like addition :)
二进制补码非常适合做减法,就像加法一样:)
11111110 (254 or -2) +00000001 ( 1) --------- 11111111 (255 or -1) 11111111 (255 or -1) +00000001 ( 1) --------- 100000000 ( 0 + 256)
回答by Goz
That is two's complementencoding.
那是二进制补码编码。
The main bonus is that you get the same encoding whether you are using an unsigned or signed int. If you subtract 1 from 0 the integer simply wraps around. Therefore 1 less than 0 is 0xFFFFFFFF.
主要的好处是无论您使用的是无符号整数还是有符号整数,都可以获得相同的编码。如果从 0 中减去 1,整数就会简单地环绕。因此,1 小于 0 是 0xFFFFFFFF。
回答by trinalbadger587
Because the bit pattern for an int -1 is FFFFFFFF in hexadecimal unsigned. 11111111111111111111111111111111 binary unsigned. But in int the first bit signifies whether it is negative. But in unsigned int the first bit is just extra number because a unsigned int cannot be negative. So the extra bit makes an unsigned int able to store bigger numbers. As with an unsigned int 11111111111111111111111111111111 (binary) or FFFFFFFF (hexadecimal) is the biggest number a uint can store. Unsigned Ints are not recommended because if they go negative then it overflows and goes to the biggest number.
因为 int -1 的位模式在十六进制无符号中是 FFFFFFFF。11111111111111111111111111111111 二进制无符号。但是在 int 中,第一位表示它是否为负。但是在 unsigned int 中,第一位只是额外的数字,因为 unsigned int 不能为负。所以额外的位使得 unsigned int 能够存储更大的数字。与 unsigned int 一样,11111111111111111111111111111111(二进制)或 FFFFFFFF(十六进制)是 uint 可以存储的最大数字。不建议使用无符号整数,因为如果它们变为负数,则它会溢出并变为最大数。