I have recently been studying the one’s complement system of representing numbers and from what I understand there are two variants of the number 0. There is a negative zero (-0) and a positive zero (+0).
My question is, on a one’s complement architecture, how exactly is this anomaly treated in C? Does C make a distinction between -0 and +0 or are both of these forms simply treated as zero.
If it is the case that both +0 and -0 return TRUE when tested for zero, then I am wondering how the following sample code would work that calculates the number of set bits in an integer if we enter -0 as its input.
int bitcount(int x)
{
int b;
for (b = 0; x != 0; b++)
x &= (x-1);
return b;
}
Since -0, in one’s complement, has all of its bits set to 1, -0 should return the highest amount of bits set out of any other number; however, it appears that this code would fail the loop test condition of x != 0
, and would not even enter the loop, giving an incorrect result.
Would it be possible somehow in C, in a one's complement architecture, to make the loop condition sensitive to positive zeros as in: x != +0
Also, if I would subtract 1 from +0, would I get -0, or -1. In other words, does +0 - 1 = -0 in a one’s complement architecture?
All in all, not to go too far off course in this discussion, I am just wondering how C treats the peculiarities of the number 0 in a one’s complement architecture.
It is implementation-defined whether, on a ones-complement architecture, the value "with sign bit and all value bits 1" is a "trap representation" or a normal value. If it is a trap representation, any attempt to do anything with it, or even create it in the first place, provokes undefined behavior. If it is a normal value, it is a "negative zero", and there is an explicit list of operations that are allowed to produce it:
If the implementation supports negative zeros, they shall be generated only by:
- the &, |, ^, ~, <<, and >> operators with operands that produce such a value;
- the +, -, *, /, and % operators where one operand is a negative zero and the result is zero;
- compound assignment operators based on the above cases.
It is unspecified whether these cases actually generate a negative zero or a normal zero, and whether a negative zero becomes a normal zero when stored in an object.
(C11/N1570, section 6.2.6.2 paragraph 3.)
It also appears to be unspecified (by omission) whether negative zero compares equal to normal zero. Similar rules apply to sign-and-magnitude architectures.
So, what this boils down to is, the behavior of your example code is implementation-defined, and the implementation may not define it helpfully. You would need to consult the compiler and architecture manuals for this hypothetical ones-complement machine to figure out whether it does what you want it to do.
However, the entire question is moot, because nobody has manufactured a non-twos-complement CPU in at least 25 years. One hopes that a future revision of the C standard will cease to allow for the possibility; it would simplify many things.