> Why is this restriction applied to only narrow unsigned character types?
This restriction (all bits of the object representation participate in the value representation) applies to all narrow character types:
char,
signed char and
unsigned char. The reason is that the IS requires that any object can be inspected as a sequence of bytes. For instance,
ostream::write and a subsequent
std::istream::read (write and subsequently read the object representation as a sequence of
char) should work correctly for
StandardLayout types.
That each possible bit pattern of the value representation represents a distinct number is necessarily true only for unsigned character types (eg. the representation of integral types may be the ones’ complement representation in a conforming implementation).
> Specifically, when is this not true in practice?
An example would be the type
long double in a GNU / x64 implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
#include <iostream>
#include <limits>
#include <bitset>
int main()
{
std::cout << "size in bytes: " << sizeof(long double) << '\n'
<< "bits per byte: " << std::numeric_limits<unsigned char>::digits << '\n'
<< "bits in object representation: " << sizeof(long double) * std::numeric_limits<unsigned char>::digits << "\n\n"
<< "bits in mantissa: " << std::numeric_limits<long double>::digits << '\n'
<< "min exponent: " << std::numeric_limits<long double>::min_exponent << '\n'
<< "max exponent: " << std::numeric_limits<long double>::max_exponent << '\n' ;
}
|
size in bytes: 16
bits per byte: 8
bits in object representation: 128
bits in mantissa: 64
min exponent: -16381
max exponent: 16384 |
http://coliru.stacked-crooked.com/a/a51c5cb95b8ff162
ie. 128 bits in the object representation of which only 80 bits (mantissa:64, biased exponent:15, sign:1) are used in the value representation.