我正在尝试理解严格别名规则。通过阅读什么是严格别名规则的回答,我有一些进一步的问题。这里我借用了那篇文章中的例子:
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]);
}
现在考虑以下代码 (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);
对于上述代码,作者解释了由于未定义行为可能会发生的情况。发送的消息可能包含全0:在优化过程中,编译器可能假设 msg
和 buff
指向不同的内存块,并决定对 msg
的写入不会影响到 buff
。
但是下面的代码(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);
发送的消息是否可以保证按照预期进行(就好像关闭了严格别名编译标志一样)?如果是这样,那么仅仅因为*char
(msg
)指向与buff
相同的位置,编译器应该并将会注意到它,并且避免在(A)中可能出现的上述优化吗?
然而,我又读了一篇针对帖子Strict aliasing rule and 'char *' pointers的另一个评论,该评论表示使用*char
指针写入所引用的对象是未定义行为。因此,代码(B)仍然可能导致类似的意外行为吗?