我最近在这个平台上工作,遗留代码库为此发出大量“cast increases required alignment to N”警告,其中 N 是 cast 目标的大小。
struct Message
{
int32_t id;
int32_t type;
int8_t data[16];
};
int32_t GetMessageInt(const Message& m)
{
return *reinterpret_cast<int32_t*>(&data[0]);
}
希望很明显,“真正的”实现会稍微复杂一些,但基本要点是我有来自某处的数据,我知道它是对齐的(因为我需要要对齐的 id 和类型),但我得到的消息是强制转换正在增加对齐,在本例中,为 4。
现在我知道我可以用编译器的参数来抑制警告,我知道我可以先将括号内的位转换为 void*,但我真的不想遍历每一段代码这需要这种操作(有很多,因为我们从磁盘加载了大量数据,并且这些数据以字符缓冲区的形式出现,以便我们可以轻松地进行指针前进),但是任何人都可以给我关于这个问题的任何其他想法?我的意思是,对我来说,这似乎是一个您不想发出警告的重要且常见的选项,如果实际上有可能做错,那么抑制警告将无济于事。最后,编译器难道不能像我一样知道所讨论的对象实际上是如何在结构中对齐的,所以它应该能够不必担心该特定对象的对齐,除非它被撞了一两个字节?
最佳答案
一个可能的替代方案是:
int32_t GetMessageInt(const Message& m)
{
int32_t value;
memcpy(&value, &(data[0]), sizeof(int32_t));
return value;
}
对于 x86 架构,对齐并没有那么重要,它更像是一个与您提供的代码并不真正相关的性能问题。对于其他架构(例如 MIPS),未对齐的访问会导致 CPU 异常。
好的,这是另一种选择:
struct Message
{
int32_t id;
int32_t type;
union
{
int8_t data[16];
int32_t data_as_int32[16 * sizeof(int8_t) / sizeof(int32_t)];
// Others as required
};
};
int32_t GetMessageInt(const Message& m)
{
return m.data_as_int32[0];
}
下面是上述内容的变体,其中包括来自 cpstubing06
的建议:
template <size_t N>
struct Message
{
int32_t id;
int32_t type;
union
{
int8_t data[N];
int32_t data_as_int32[N * sizeof(int8_t) / sizeof(int32_t)];
// Others as required
};
static_assert((N * sizeof(int8_t) % sizeof(int32_t)) == 0,
"N is not a multiple of sizeof(int32_t)");
};
int32_t GetMessageInt(const Message<16>& m)
{
return m.data_as_int32[0];
}
// Runtime size checks
template <size_t N>
void CheckSize()
{
assert(sizeof(Message<N>) == N * sizeof(int8_t) + 2 * sizeof(int32_t));
}
void CheckSizes()
{
CheckSize<8>();
CheckSize<16>();
// Others as required
}
关于c++ - 警告 : cast increases required alignment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2741787/