为什么(18446744073709551615 == -1)是真的?

时间:2016-11-15 10:58:38

标签: c++ equality unsigned signed integer-overflow

当我在string::npos工作时,我发现了一些内容,我无法在网上找到任何解释。

(string::npos == ULONG_MAX)

(string::npos == -1)

是真的。

所以我尝试了这个:

(18446744073709551615 == -1)

这也是事实。

怎么可能?是因为二元对话吗?

4 个答案:

答案 0 :(得分:10)

18,446,744,073,709,551,615

提到的这个数字18,446,744,073,709,551,615实际上是2^64 − 1。这里重要的是2^64-1本质上是从0开始的2^64。无符号整数的第一位数字是0,而不是1。因此,如果最大值为1,则有两个可能的值:01(2)。

让我们看看64位二进制文​​件中的2^64 - 1,所有位都是打开的。

1111111111111111111111111111111111111111111111111111111111111111b

-1

让我们看看64位二进制文​​件中的+1

0000000000000000000000000000000000000000000000000000000000000001b

要使其在恭维(OCP)中为负,我们将这些位取反。

1111111111111111111111111111111111111111111111111111111111111110b

计算机很少使用OCP,而是使用 Two's Compliment (TCP)。要获取TCP,请在OCP中添加一个。

1111111111111111111111111111111111111111111111111111111111111110b (-1 in OCP)
+                                                              1b (1)
-----------------------------------------------------------------
1111111111111111111111111111111111111111111111111111111111111111b (-1 in TCP)

“但是,请稍等”,您问,如果“恭维恭喜-1是,

1111111111111111111111111111111111111111111111111111111111111111b

并且,如果二进制文件2^64 - 1

1111111111111111111111111111111111111111111111111111111111111111b

那么他们是平等的!而且,这就是您所看到的。您正在将有符号的64位整数与无符号的64位整数进行比较。在C ++中,这意味着将有符号值转换为无符号,编译器会这样做。

更新

对于技术性更正thanks to davmac in the comments,实际上是用该语言指定从-1的{​​{1}}到相同大小的signed类型的转换,而不是架构的功能。综上所述,您可能会发现上面的答案对于理解支持两个人称赞但缺乏确保您可以依靠的结果的规范的语言很有帮助。

答案 1 :(得分:8)

string::npos被定义为constexpr static std::string::size_type string::npos = -1;(或者如果它在类定义中被定义为constexpr static size_type npos = -1;但是它真的无关紧要。)

转换为无符号类型的负数的回绕(std::string::size_type基本上是std::size_t,它是无符号的)完全由标准定义。 -1包含无符号类型的最大可表示值,在您的情况下为18446744073709551615。请注意,确切的值是实现定义的,因为std::size_t的大小是实现定义的(但能够保持相关系统上最大可能数组的大小)。

答案 2 :(得分:1)

根据C ++标准(文件编号:N3337或文件号:N4296)ApplicationWindow { visible: true width: 500 height: 500 Rectangle { width: 100 height: 100 anchors.centerIn: parent color: "red" Rectangle { id: iRect color: "blue" width: 40 height: 40 anchors.top: parent.top states: [State { name: "up" when: iMouseArea.pressed PropertyChanges { target: iRect anchors.topMargin: 50 } }] transitions: [ Transition { to: "up" NumberAnimation { properties:"anchors.topMargin"; easing.type: Easing.InOutQuad;duration: 300 } } ] } MouseArea{ id: iMouseArea anchors.fill: parent } } } 的定义方式如下

std::string::npos

其中std :: string :: size_type是一些无符号整数类型。所以std :: string :: npos等于-1并不是什么好事。初始化程序将转换为static const size_type npos = -1; 的tyhpe。

至于这个等式

std::string::npos

然后它表示类型(string::npos == ULONG_MAX) is true, 在使用的实现std::string::npos中具有类型。此类型通常对应于unsigned long类型。

在这个等式中

size_t

左边的文字有一些无符号整数类型,适合存储这么大的文字。因此,通过传播符号位,右操作数也被转换为这种无符号类型。由于左操作数表示该类型的最大值,因此它们是相等的。

答案 3 :(得分:0)

这是关于签名溢出以及负数存储为2s补码的事实。意味着要获得负数的绝对值,您可以反转所有位并添加一个。进行8位比较时的含义255和-1具有相同的二进制值11111111.这同样适用于更大的整数

https://en.m.wikipedia.org/wiki/Two%27s_complement