是否有可能区分0和-0?

我知道整数值0-0本质上是相同的。 但是,我想知道是否可以区分它们。

例如,我怎么知道一个variables是否被赋值为-0

 bool IsNegative(int num) { // How ? } int num = -0; int additinon = 5; num += (IsNegative(num)) ? -addition : addition; 

内存中的值-0是否与-0保存?

这取决于您所瞄准的机器。

在一个使用二进制补码表示整数的机器上, 0-0之间的0 -0 没有区别 (它们具有相同的表示)

如果你的机器使用补码 ,你肯定可以

 0000 0000 -> signed 0 1111 1111 -> signed −0 

很明显,我们正在讨论使用本地支持 ,x86系列处理器原生支持有符号数的二进制补码表示。 使用其他表示方式绝对有可能,但可能效率较低,需要更多的指示。

(正如JerryCoffin所指出的那样:即使补码被认为主要是出于历史的原因,有符号的幅度表示仍然是相当普遍的,并且对于负的和正的零有一个单独的表示)

对于一个int (在几乎通用的“2的补码”表示中) 0-0的表示是相同的。 (对于其他数字表示,例如IEEE 754浮点,它们可以是不同的。)

我们首先用二进制补码表示0(当然还有许多其他的系统和表示法,这里我就是指这个特定的一个),假设8位,零是:

 0000 0000 

现在让我们翻转所有的位并加1来得到2的补码:

 1111 1111 (flip) 0000 0001 (add one) --------- 0000 0000 

我们得到了0000 0000 ,这也是-0的表示。

但是请注意,在1的补码中,有符号0是0000 0000,而-0是1111 1111。

我已经决定离开这个答案了,因为C和C ++实现通常是密切相关的,但实际上并不像我以前那样推迟到C标准。 关键是C ++标准没有规定像这样的情况会发生什么。 在现实世界中,非二重补充表征是非常罕见的,而且即使它们确实存在,它们在许多情况下经常隐藏它们的差异,而不是将其暴露为某人可能期望发现的东西。


它们存在的整数表示中的负零的行为不像C标准那样严格定义在C ++标准中。 但是,它引用了C标准(ISO / IEC 9899:1999)作为最高级别的规范性参考文献[1.2]。

在C标准[6.2.6.2]中,负的零只能是按位运算的结果,或者已经存在负零的运算(例如,将负的零乘以或除以一个值,或者将负的零加到零) – 将一元减运算符应用于正常零值,如您的示例,因此保证导致一个正常的零。

即使在可能产生负的零的情况下,即使在支持负零的系统上,也不能保证它们会:

这些情况实际上是否产生负的零或正常的零,以及当存储在对象中时负零是否变成正常的零是没有规定的。

因此,我们可以得出结论: 不,没有可靠的方法来检测这种情况。 即使不是因为在现代计算机系统中非二补码的performance是非常罕见的事实。

就C ++标准而言,它没有提到“负零”这个词,除非注意到[3.9.1]第7段中的规定允许它们,否则就很less讨论有符号幅度和补码表示的细节。

如果您的机器具有不同的表示forms-0+0 ,则memcmp将能够区分它们。

如果存在填充位,则实际上可能有多个表示除了零以外的值。

在C ++语言规范中,不存在负数为零的整数。

这两个词所具有的唯一含义是一元运算符-应用于0 ,就像三加五只是应用于35的二元运算符一样。

如果存在一个明显的负零 ,那么二进制补码(整数types的最常见表示)将不足以代表C ++实现,因为无法表示两种forms的零。


相比之下,浮点(IEEE)有单独的正和负零。 例如,他们可以被区分,当他们分开1。 正零点产生正无穷; 负零产生负无穷。


但是,如果int 0(或任何其他types的int或任何其他types的值)存在不同的内存表示,则可以使用memcmp来发现:

 #include <string> int main() { int a = ... int b = ... if (memcmp(&a, &b, sizeof(int))) { // a and b have different representations in memory } } 

当然,如果发生这种情况,除了直接记忆操作之外,这两个值仍将以完全相同的方式工作。

为了简化我发现它更容易可视化。

typesint (_32)以32位存储。 32位表示2 ^ 32 = 4294967296个唯一值 。 因此:

无符号整型数据范围是0到4,294,967,295

在负值的情况下,这取决于它们如何被存储。 以防万一

  • 二补 -2,147,483,648至2,147,483,647
  • 补码 -2,147,483,647至2,147,483,647

补码值-0存在的情况下。