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

Viewed 361

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.

2 Answers

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.

Related