With GNU GCC 4.7.0+ I got a few strict aliasing warnings, which I would like to resolve.
I have a payload (from hardware):
unsigned char payload[davidlt::PAYLOAD_SIZE];
I had this line:
*(uint32_t*)(payload + davidlt::DATA_OFFSET) = (pid & davidlt::PID_MASK) << davidlt::PID_SHIFT;
This creates a pointer to a specific location in payload and 4 bytes are interpreted as uint32_t
. A new value uint32_t
type is calculated and replaced in the payload.
I get:
warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
I was hoping to solve it by using reinterpret_cast
, but I get the same warning.
*reinterpret_cast<uint32_t *>(payload + davidlt::DATA_OFFSET) = (pid & davidlt::PID_MASK) << davidlt::PID_SHIFT;
As I understood you can convert whatever data to char
or unsigned char
, which is allowed, but that works only one way.
One solution would be to make a union
. Aren't were any other way to create a reference of different type to unsigned char
data?
Thanks! david
Yes, viewing data as char or unsigned char is allowed, but not the reverse.
Instead you should use memcpy in this case. Your line takes a pid
value, masks it, shifts it, and then inserts it into the payload. A direct translation of this would be:
unsigned char payload[davidlt::PAYLOAD_SIZE];
uint32_t payload_pid = (pid & davidlt::PID_MASK) << davidlt::PID_SHIFT;
std::memcpy(payload + davidlt::DATA_OFFSET, &payload_pid, sizeof payload_pid);
Another alternative would be to create your payload as a standard layout type with the appropriate size and members, and then to view it as an unsigned char array. Assuming you're in control of creating the payload:
struct Payload {
...
uint32_t pid;
...
} payload;
payload.pid = (pid & davidlt::PID_MASK) << davidlt::PID_SHIFT;
static_assert(davidlt::PAYLOAD_SIZE == sizeof(Payload), "");
unsigned char (&payload_as_char)[davidlt::PAYLOAD_SIZE] = reinterpret_cast<unsigned char (&)[davidlt::PAYLOAD_SIZE]>(&payload);
This isn't violating the strict aliasing rule because it's going the right direction now.