I am trying to understand the strict aliasing rule. By reading the answer to What is the strict aliasing rule , I have some further questions. Here I borrow the example from that post:
struct Msg { uint32_t a, b; }
void SendWord(uint32_t);
void SendMessage(uint32_t* buff, uint32_t buffSize)
{
for (uint32_t i = 0; i < buffSize; ++i) SendWord(buff[i]);
}
Now consider the following code (A):
uint32_t *buff = (uint32_t*)malloc(sizeof(Msg));
std::memset(buff, 0, sizeof(Msg));
Msg *msg = (Msg*)buff; // Undefined behavior.
for (uint32_t i = 0; i < 10; ++i)
{
msg->a = i;
msg->b = i + 1;
SendMessage(buff, 2);
}
free(buff);
For the above code, the author explained what might happen due to the UB. The message sent could contain all 0s: during optimization, the compiler may assume msg
and buff
point to disjoint memory blocks, and then decide the writes to msg
do not affect buff
.
But how about the following code (B):
uint32_t *buff = (uint32_t*)malloc(sizeof(Msg));
std::memset(buff, 0, sizeof(Msg));
unsigned char *msg = (unsigned char*)buff; // Compliant.
for (uint32_t i = 0; i < sizeof(Msg); ++i)
{
msg[i] = i + 1;
SendMessage(buff, 2);
}
free(buff);
Is the sent message guaranteed to be as intended (as if the strict aliasing complier flag is off) ? If so, is it simply because a *char
(msg
) points to the same place as buff
, the compiler should and will notice it, and refrain from the possible, aforementioned optimization in (A) ?
Yet then I read another comment under the post Strict aliasing rule and 'char *' pointers, saying that it is UB to use the *char
pointer to write the referenced object. So again, code (B) could still result in similar, unexpected behavior ?