How does C treat the number 0 in a one’s complement architecture?

浪尽此生 提交于 2019-12-09 18:43:41

问题


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.


回答1:


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.




回答2:


To answer your question, there are 2 possibilities to consider:

  • if the bit pattern with all bits set is a trap representation (which is explicitly allowed by the C Standard), passing such a value to the function has undefined behavior.

  • if this bit pattern is allowed, it the one's complement representation of negative zero, which should compare equal to 0. In this case, the function as written will have defined behavior and will return 0 since the initial loop test is false.

The result would be different if the function was written this way:

int bitcount32(int x) {
    // naive implementation assuming 31 value bits
    int count = 0, b;
    for (b = 0; b < 31; b++) {
        if (x & (1 << b))
           count++;
        }
    }
    return count;
}

On this one's complement architecture, bitcount32(~0) would evaluate to 31:

(x & (1 << b)) with x the argument with the specific bit pattern and b in range for 1 << b to be defined, evaluates to 1 << b, a different value from the result on two's complement and sign/magnitude architectures.

Note however that the posted implementation has undefined behavior for an argument of INT_MIN as x-1 causes a signed arithmetic overflow. It is highly advisable to always use unsigned types for bitwise and shift operations.



来源:https://stackoverflow.com/questions/45260365/how-does-c-treat-the-number-0-in-a-one-s-complement-architecture

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!