15

Bitwise operators (~, &, | and ^) operate on the bitwise representation of their promoted operands. Can such operations cause undefined behavior?

For example, the ~ operator is defined this way in the C Standard:

6.5.3.3 Unary arithmetic operators

The result of the ~ operator is the bitwise complement of its (promoted) operand (that is, each bit in the result is set if and only if the corresponding bit in the converted operand is not set). The integer promotions are performed on the operand, and the result has the promoted type. If the promoted type is an unsigned type, the expression ~E is equivalent to the maximum value representable in that type minus E.

On all architectures, ~0 produces a bit pattern with the sign bit set to 1 and all value bits set to 1. On a one's complement architecture, this representation correspond to a negative zero. Can this bit pattern be a trap representation?

Are there other examples of undefined behavior involving simple bitwise operators for more common architectures?

M.M
  • 138,810
  • 21
  • 208
  • 365
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 3
    No, on a one's complement architecture, `~0` produces a bit pattern with *all* bits set to `1`. Why do you think the non-sign bits would remain zero? That's not bitwise complement. – Tom Karzes Sep 24 '17 at 07:45
  • I'm not quite sure why that's an example of undefined behavior? Seems pretty well-defined to me. – JJJ Sep 24 '17 at 07:48
  • @JJJ: manipulating a trap representation has undefined behavior. The example is a corner case in an ancient architecture. – chqrlie Sep 24 '17 at 07:49
  • 3
    1999 C standard, section 6.5 para 4. "Some operators (the unary operator `~`, and the binary operators `<<`, `>>`, `&`, `^`, and `|`, collectively described as bitwise operators) are required to have operands that have integer type. These operators return values that depend on the internal representations of integers, and have **implementation-defined and undefined aspects for signed types**." (bold emphasis mine). – Peter Sep 24 '17 at 07:49
  • I believe any potential trap conditions would only apply to signed integer types. If you want to avoid traps, and just obtain the resulting bit pattern, use unsigned integer types. – Tom Karzes Sep 24 '17 at 07:52
  • The same wording is present in the C11 Standard. There are multiple undefined aspects for the `<<` and `>>` operators, I am asking if there are also implied undefined aspects in the other bitwise operators. – chqrlie Sep 24 '17 at 07:52
  • That clause says there is. Remember there are two ways behaviour can be undefined in the standards. One is that the standard states the behaviour is undefined. One is that the standard provides no definition of the behaviour. For signed operands or results, the value obtained by bitwise operations is undefined in several cases (e.g. if the operand has a negative value). – Peter Sep 24 '17 at 07:56
  • 1
    Duplicate of https://stackoverflow.com/questions/11644362/ – M.M Sep 25 '17 at 11:32
  • Also relevant, https://stackoverflow.com/questions/45260365/ – M.M Sep 25 '17 at 11:35
  • @M.M: my question is indeed a duplicate, I had not seen that question, and R.'s answer is perfect. The other link is interesting too, mixing signed values and bitwise operations is a bad idea. – chqrlie Sep 25 '17 at 13:35
  • 1
    @chqrlie OK, although that thread could do with Standard quotes. Maybe also relevant [this thread](https://stackoverflow.com/questions/24665835/what-is-the-definition-of-arithmetic-operation-in-c99) - because of the footnote in the standard that an arithmetic operation cannot produce a trap representation. (Presumably that means "except for the negative zero case already defined") – M.M Sep 26 '17 at 00:07
  • 1
    Removed dual tag -- the standard quotes in the question and answers all address C; the C++ is a different language and different language questions shouldn't be dual tagged unless they are about interoperability etc. – M.M Aug 05 '21 at 21:21

1 Answers1

11

For one's complement systems, there's explicitly listed the possibility of trap values for those that do not support negative zeros in signed integers (C11 6.2.6.2p4):

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

Then again, one's complement systems are not exactly common; as for example GCC doesn't support any!

C11 does imply that the implementation-defined and undefined aspects are just allowed for signed types (C11 6.5p4).