-Werror=C中的严格别名错误
我正在尝试调用此函数-Werror=C中的严格别名错误,c,C,我正在尝试调用此函数 static inline void insert(Buffer *buf, double f, size_t index) { insert_64(buf, *(uint64_t *)&f, index); } 但是,我得到了这个错误: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing] 不知道哪里出错。正如
static inline void insert(Buffer *buf, double f, size_t index)
{
insert_64(buf, *(uint64_t *)&f, index);
}
但是,我得到了这个错误:
error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
不知道哪里出错。正如评论中提到的,尝试将指向一种类型的指针转换为另一种类型的指针会违反严格的别名规则。您可以通过使用
memcpy
将字节从一种类型复制到另一种类型来解决此问题:
uint64_t x;
memcpy(&x, &f, sizeof(f));
请注意,x
包含的内容取决于实现,即double
的表示形式是什么,是系统大端还是小端,是double
64位,等等
不知道我错在哪里
*(uint64\u t*)&f
打破了严格的别名规则。看
要修复此问题,请使用memcpy()
以及由或union
回答的方法。联合
处理严格的别名规则
void insert2(Buffer *buf, double f, size_t index) {
union {
double d;
uint64_t u64;
} u = { f };
insert_64(buf, u.u64, index);
}
或者也可以使用复合文字(从C99开始提供)
对于C11,我将添加以下内容,以便将来对正确性进行评估
_Static_assert(sizeof (double) == sizeof (uint64_t), "Unexpected sizes");
注意:很少有平台具有不同的endian/integer和FP类型。
*(uint64\u t*)和f
。你不能假装指向一个float
的指针是指向一个uint64\u t
的指针,然后侥幸逃脱。可能重复@leedinelcrocker取消引用新指针是UB,OP肯定是做错了什么。看看这里:不,这不仅仅是关于可移植性。打破严格的别名规则并进行一些优化可能会导致更有趣的事情。请看这里:
_Static_assert(sizeof (double) == sizeof (uint64_t), "Unexpected sizes");