Strict C ++ 11 alias rules allow access to uint64_t via char *, char (&) [N], even std :: array <char, N> & with -fstrict-aliasing -Wstrict-aliasing = 2?
According to this stackoverflow answer about strict C ++ 11/14 alias rules :
If a program tries to access the stored value of an object through a gl value other than one of the following types, the behavior is undefined:
dynamic type of object
cv-qualified version of the dynamic type of an object,
- a type similar (as defined in 4.4) for the dynamic type of an object,
- a type that is a signed or unsigned type corresponding to a dynamic type of an object,
- a type that is a signed or unsigned type corresponding to the receipt version of the dynamic type of an object,
- an aggregate or union type that includes one of the above types among its elements or non-static data elements (including a recursively element or non-static subaggregate or contains union data element),
- a type that is (possibly cv-qualified) a base class type of a dynamic object type,
- a or .
char
unsigned char
we can access another type of storage using
(1) char *
(2) char(&)[N]
(3) std::array<char, N> &
regardless of undefined behavior ?
constexpr uint64_t lil_endian = 0x65'6e'64'69'61'6e;
// a.k.a. Clockwise-Rotated Endian which allocates like
// char[8] = { n,a,i,d,n,e,\0,\0 }
const auto& arr = // std::array<char,8> &
reinterpret_cast<const std::array<char,8> &> (lil_endian);
const auto& carr = // char(&)[8]>
reinterpret_cast<const char(&)[8]> (lil_endian);
const auto* p = // char *
reinterpret_cast<const char *>(std::addressof(lil_endian));
int main()
{
const auto str1 = std::string(arr.crbegin()+2, arr.crend() );
const auto str2 = std::string(std::crbegin(carr)+2, std::crend(carr) );
const auto sv3r = std::string_view(p, 8);
const auto str3 = std::string(sv3r.crbegin()+2, sv3r.crend() );
auto lam = [](const auto& str) {
std::cout << str << '\n'
<< str.size() << '\n' << '\n' << std::hex;
for (const auto ch : str) {
std::cout << ch << " : " << static_cast<uint32_t>(ch) << '\n';
}
std::cout << '\n' << '\n' << std::dec;
};
lam(str1);
lam(str2);
lam(str3);
}
all lambda calls make:
endian
6
e : 65
n : 6e
d : 64
i : 69
a : 61
n : 6e
godbolt.org/g/cdDTAM (enable -fstrict-aliasing -Wstrict-aliasing = 2)
char(&)[N]
std::array<char, N>
undefined. . , char(&)[N]
std::array<char, N>
- , char
.
, , std::memcpy
, [basic.types]/2:
( ) - T, , T, ([intro.memory]), , char, unsigned char
std::byte
([cstddef.syn]). , . [:
#define N sizeof(T) char buf[N]; T obj; // obj initialized to its original value std::memcpy(buf, &obj, N); // between these two calls to std::memcpy, obj might be modified std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type holds its original value
- ]