If a C++14
implementation includes padding bits in the underlying bytes of an unsigned int
, does the standard specify if bitwise operations must not be performed on padding bits ?
Additionally, does the C++14 standard specify if equality and relational
operators must ignore the padding bits ?
If there is a lack of specification on that matter, is there some kind of consensus on the expected behavior of those operators on padding bits?
I found conflicting answers on Stack Overflow. Lightness Races in Orbit and ecatmur say that bitwise operators are unsuitable for arithmetic because they are applied on all bits (including padding bits), while Christoph and Bartek Banachewicz say that the bitwise operators work on the logical value of integers and ignore padding.
Related answers: on the existence of padding bits (1, 2, 3), on the absence of clear C++ specification (4).
Definition of padding bits in C++14 - § 3.9.1 - Fundamental types:
For narrow character types, all bits of the object representation participate in the value representation. For unsigned narrow character types, all possible bit patterns of the value representation represent numbers. These requirements do not hold for other types.
Definition of object representation and value representation in C++14 - § 3.9 - Types:
The object representation of an object of type
T
is the sequence of Nunsigned char
objects taken up by the object of typeT
, where N equalssizeof(T)
. The value representation of an object is the set of bits that hold the value of typeT
. For trivially copyable types, the value representation is a set of bits in the object representation that determines a value, which is one discrete element of an implementation-defined set of values.44Footnote 44) The intent is that the memory model of C++ is compatible with that of ISO/IEC 9899 Programming Language C.
Definition of bitwise AND in C++14 - § 5.11 - Bitwise AND operator:
The usual arithmetic conversions are performed; the result is the bitwise AND function of the operands. The operator applies only to integral or unscoped enumeration operands.
Definition of addition in C++14 - § 5.7 - Additive operators:
The usual arithmetic conversions are performed for operands of arithmetic or enumeration type. For addition, [...] both operands shall have arithmetic or unscoped enumeration type [...]. The result of the binary
+
operator is the sum of the operands.
Bit padding is the addition of one or more extra bits to a transmission or storage unit to make it conform to a standard size. Some sources identify bit padding as a type of bit stuffing.
The ~ (bitwise negation) operator yields the bitwise complement of the operand. In the binary representation of the result, every bit has the opposite value of the same bit in the binary representation of the operand. The operand must have an integral type.
<< is the left shift operator. It is shifting the number 1 to the left 0 bits, which is equivalent to the number 1 .
The ^ (bitwise XOR) in C or C++ takes two numbers as operands and does XOR on every bit of two numbers. The result of XOR is 1 if the two bits are different. The << (left shift) in C or C++ takes two numbers, left shifts the bits of the first operand, the second operand decides the number of places to shift.
First of all, the C++ standard itself barely says about padding bits. Essentially all discussion of padding bits comes from the base document (i.e., the C standard).
So the real question is what the C standard says about things. Its footnote 54 gives a fairly concise summary of padding bits in general:
Some combinations of padding bits might generate trap representations, for example, if one padding bit is a parity bit. Regardless, no arithmetic operation on valid values can generate a trap representation other than as part of an exceptional condition such as an overflow. All other combinations of padding bits are alternative object representations of the value specified by the value bits.
Operators might change a padding big. The obvious case would be a padding bit that represented parity. If you change a value's parity, the parity bit would change to match.
The "alternative object representations of the value" part basically mean that as long as you stay "in bounds", the padding bits don't affect your results. For example, if you compare two values, only the representation bits are used to determine the results (6.2.6.1/4):
Two values (other than NaNs) with the same object representation compare equal, but values that compare equal may have different object representations.
The times and places you have to be careful mostly involve undefined or implementation defined behavior. For example, if you store a value into one value in a union, then retrieve a different value in the union, it's possible the second could have the padding bits set to a trap representation, so even looking at the value that way could crash your program (or whatever).
Likewise, if you were to take two values, memcpy
each to an buffer of unsigned char, some bits of those bytes might compare as not-equal, even if the values they represented did compare equal.
One place this can bit you even if you never use mempy
directly is with some of the compare-and-exchange operators. These use memcpy
and memcmp
for the underlying operations, so they're also subject to comparing not equal, even though the values being represented are equal:
[atomics.types.operations]/23:
The memcpy and memcmp semantics of the compare-and-exchange operations may result in failed comparisons for values that compare equal with operator== if the underlying type has padding bits, trap bits, or alternate representations of the same value. Thus, compare_exchange_strong should be used with extreme care. On the other hand, compare_exchange_weak should converge rapidly.
Side note: the two large quotes are descriptive, not normative--from a normative viewpoint, padding bits have almost no meaning; almost anything that could expose padding bits or their values involves implementation defined or undefined behavior. The only normative quote here is the one that basically says: "padding bits have no effect."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With