Fil*_*inx 92 c++ int zero negative-number
我知道整数值0和-0基本相同.但是,我想知道是否有可能区分它们.
例如,我如何知道是否分配了变量-0?
bool IsNegative(int num)
{
// How ?
}
int num = -0;
int additinon = 5;
num += (IsNegative(num)) ? -addition : addition;
Run Code Online (Sandbox Code Playgroud)
-0保存在内存中的值与完全相同0吗?
Mar*_* A. 111
这取决于您要定位的机器.
在一个使用一台机器2的补码表示的整数有在位级无差异之间0和-0(他们有相同的表示)
如果你的机器使用了一个补充,你绝对可以
0000 0000 -> signed? 0?
1111 1111 -> signed ?0
Run Code Online (Sandbox Code Playgroud)
显然我们正在谈论使用原生支持,x86系列处理器本身支持签名数字的二进制补码表示.使用其他表示肯定是可能的,但可能效率较低,需要更多指令.
(正如JerryCoffin所指出的那样:即使一个人的补充主要是出于历史原因而被考虑,签名的量级表示仍然相当普遍,并且确实有一个单独的表示负数和正数零)
Mar*_*oun 12
让我们从2的补码中表示0开始(当然存在许多其他系统和表示,这里我指的是这个特定的),假设8位,零是:
0000 0000
Run Code Online (Sandbox Code Playgroud)
现在让我们翻转所有位并加1以获得2的补码:
1111 1111 (flip)
0000 0001 (add one)
---------
0000 0000
Run Code Online (Sandbox Code Playgroud)
我们得到了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]中,负零只能是按位运算的结果,或者已经存在负零的运算(例如,将负零乘以或除以负值,或者将负零加到零) - 将一元减运算符应用于正常零的值,如在您的示例中,因此保证导致正常零.
即使在可以产生负零的情况下,也无法保证它们即使在支持负零的系统上也是如此:
未指定这些情况是否实际产生负零或正常零,以及当存储在对象中时负零是否变为正常零.
因此,我们可以得出结论:不,没有可靠的方法来检测这种情况.即使不是因为非二进制补码表示在现代计算机系统中非常罕见.
就其本身而言,C++标准没有提及"负零"这一术语,除了注意到[3.9.1第7段]允许它们之外,很少讨论有符号量和一个补码表示的细节.
在C++语言规范中,没有像负零那样的int .
这两个词有唯一意义是单目运算符-应用到0,就像三加5只是二进制运算符+适用于3和5.
如果存在明显的负零,则两个补码(整数类型的最常见表示)将是C++实现的不充分表示,因为无法表示两种形式的零.
相反,浮点(遵循IEEE)具有单独的正负零.例如,当将它们除以1时,可以区分它们.正零产生正无穷大; 负零产生负无穷大.
但是,如果碰巧有int 0(或任何int或任何其他类型的任何其他值)的不同内存表示,您可以memcmp用来发现:
#include <string>
int main() {
int a = ...
int b = ...
if (memcmp(&a, &b, sizeof(int))) {
// a and b have different representations in memory
}
}
Run Code Online (Sandbox Code Playgroud)
当然,如果确实发生了这种情况,在直接内存操作之外,这两个值仍将以完全相同的方式工作.