我最近一直在研究表示数字的一个补码系统,根据我的理解,数字0有两个变量.有一个负零(-0)和一个正零(+0).
我的问题是,在一个补码架构中,这个异常在C中究竟是如何处理的?C是否区分-0和+0,或者这两种形式都被视为零.
如果在测试零时,+ 0和-0都返回TRUE,那么我想知道如果我们输入-0作为输入,下面的示例代码将如何工作以计算整数中的设置位数.
int bitcount(int x)
{
int b;
for (b = 0; x != 0; b++)
x &= (x-1);
return b;
}
Run Code Online (Sandbox Code Playgroud)
由于-0,在一个补码中,其所有位都设置为1,-0应该返回由任何其他数字设置的最高位数; 但是,看起来这个代码会使循环测试条件失败x != 0,甚至不会进入循环,从而产生不正确的结果.
在C语言中,在一个补码架构中,是否有可能使循环条件对正零敏感,如下所示:x != +0另外,如果我从+0中减去1,我会得到-0或-1.换句话说,在一个补码架构中,+ 0 - 1 = -0?
总而言之,在本次讨论中不要偏离太远,我只是想知道C如何处理一个补码架构中数字0的特殊性.
实现定义是否在补码结构上,"带符号位和所有值位1"的值是"陷阱表示"还是正常值.如果它是一个陷阱表示,任何尝试对它做任何事情,或者甚至首先创建它,都会引发未定义的行为.如果它是一个正常值,它是一个"负零",并且有一个明确的操作列表允许产生它:
如果实现支持负零,则只能通过以下方式生成它们:
- &,|,^,〜,<<和>>运算符,其操作数产生这样的值;
- +, - ,*,/和%运算符,其中一个操作数为负零,结果为零;
- 基于上述情况的复合赋值算子.
未指定这些情况是否实际产生负零或正常零,以及当存储在对象中时负零是否变为正常零.
(C11/N1570,第6.2.6.2节,第3段)
似乎未指明(通过省略)负零比较等于正常零.类似的规则适用于符号和大小的体系结构.
因此,归结为,示例代码的行为是实现定义的,并且实现可能无法有用地定义它.您需要查阅这个假设的补充机器的编译器和体系结构手册,以确定它是否符合您的要求.
然而,整个问题没有实际意义,因为至少25年来没有人制造过非二进制补充CPU.人们希望C标准的未来修订将不再允许这种可能性; 它会简化许多事情.