The rule you are looking for is 3.9p4:
The object representation of an object of type T is a sequence of objects N unsigned char occupied by an object of type T , where N is equal to sizeof(T) . The representation of an object value is a set of bits that hold a value of type T For trivially copied types, a value representation is a set of bits in an object representation that defines a value that is one discrete element of a particular set of values.
So, if you use unsigned char , you will get the behavior defined by the implementation (any appropriate implementation should give you a guarantee of what it is).
Reading through char also legal, but then the values ββare undefined. However, you guarantee that using an unqualified char keep the value (therefore bare char cannot have traps or padding bits), according to 3.9p2:
For any object (except the subobject of the base class) of the trivially copied type T, regardless of whether the object has a valid value of type T , the basic bytes (1.7) that make up the object can be copied to a char or unsigned char array. If the contents of a char or unsigned char array are copied back to the object, the object must retain the original value.
("indefinite" values ββare slightly weaker than "implementation-defined" values ββ- the semantics are the same, but the platform is not required to document what values ββare.)
source share