Search code examples
c++c++11integerstandardsones-complement

Behaviour of negative zero on a one's complement architecture?


Consider the following code on a one's complement architecture:

int zero = 0;
int negzero = -0;
std::cout<<(negzero < zero)<<std::endl;
std::cout<<(negzero <= zero)<<std::endl;
std::cout<<(negzero == zero)<<std::endl;
std::cout<<(~negzero)<<(~zero)<<std::endl;
std::cout<<(1 << negzero)<<std::endl;
std::cout<<(1 >> negzero)<<std::endl;
  • What output would the code produce?
  • What lines are defined by the standard, what lines are implementation dependent, and what lines are undefined behaviour?

Solution

  • Based on my interpretation of the standard:

    The C++ standard in §3.9.1/p3 Fundamental types [basic.fundamental] actually throws the ball in the C standard:

    The signed and unsigned integer types shall satisfy the constraints given in the C standard, section 5.2.4.2.1.

    Now if we go to ISO/IEC 9899:2011 section 5.2.4.2.1 it gives as a forward reference to §6.2.6.2/p2 Integer types (Emphasis Mine):

    If the sign bit is zero, it shall not affect the resulting value. If the sign bit is one, the value shall be modified in one of the following ways:

    • the corresponding value with sign bit 0 is negated (sign and magnitude);

    • the sign bit has the value −(2^M) (two’s complement);

    • the sign bit has the value −(2^M − 1) (ones’ complement).

    Which of these applies is implementation-defined, as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for ones’ complement), is a trap representation or a normal value. In the case of sign and magnitude and ones’ complement, if this representation is a normal value it is called a negative zero.

    Consequently, the existence of negative zero is implementation defined.

    If we proceed further in paragraph 3:

    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.

    Consequently, it is unspecified whether the related cases that you displayed are going to generate a negative zero at all.

    Now proceeding in paragraph 4:

    If the implementation does not support negative zeros, the behavior of the &, |, ^, ~, <<, and >> operators with operands that would produce such a value is undefined.

    Consequently, whether the related operations result in undefined behaviour, depends on whether the implementation supports negative zeros.