|
|
|
|
|
by smitherfield
3051 days ago
|
|
1. Accesses through pointers type-punned to something other than `(un(signed)) char` are undefined behavior. uint64_t n = 0xdeadbeef;
uint32_t foo = (uint32_t)n; // OK
uint32_t *bar = (uint32_t*)&n; // "OK" but useless
foo = *bar; // undefined behavior!!!
uint8_t *baz = (uint8_t*)&n;
uint8_t byte = *baz; // OK, uint8_t is `unsigned char`
// Same-size integral types are OK
const volatile long long p = (const volatile long long*)&n;
const volatile long long cvll = *p; // well-defined
2. Structs are aligned to the member with the strictest alignment requirement, so a struct of a `uint64_t` and a `uint32_t` will be aligned on an 8-byte boundary, meaning its size will be 128 bits. |
|
Don't most C compilers support a pragma to control this? "#pragma pack(4)" for clang and gcc, I believe.
Given this (where I've made it add two arrays of 96-bit integers to make it easier to figure out the sizes in the assemply):
here is the code for the loop body, which the compiler unrolled to make it even easier to see how the structure is laid out: (Some white space added, and the middle cut out). The 96-bit inters are now only taking up 96-bits.