我收到了这个警告。我想定义行为,但我想保持这个代码的原样。我什么时候可以打破别名规则?
警告:解除引用类型惩罚指针将破坏严格别名规则[-Wstrict-aliasing]
String是我自己的字符串,它是一个POD。此代码从C调用.S可能是int。字符串几乎是struct String { RealString*s; }
但是模板和辅助函数。我做一个静态断言来确保String是一个pod,是4bytes,int是4bytes。我还写了一个断言,检查所有指针是否都是> = NotAPtr。它在我的新/ malloc重载。如果你建议
考虑到我遵循的规则(主要是字符串是一个pod并且总是与int相同),如果我打破别名规则会没有问题吗?这是有几次破坏它的次数之一吗?
void func(String s) {
auto v=*(unsigned int*)&s;
myassert(v);
if(v < NotAPtr) {
//v is an int
}
else{
//v is a ptr
}
}
答案 0 :(得分:4)
memcpy
。因此,请注意char*
(例如,您可以使用std::copy
。)
答案 1 :(得分:1)
如果您不能将代码更改为2个函数,那么为什么不呢(要求C99编译器使用uintptr_t
- 对于较旧的MSVC,您需要自己定义,2008/2010应该没问题):
void f(RealString *s) {
uintptr_t int = reinterpret_cast<uintptr_t>(s);
assert(int);
}
答案 2 :(得分:1)
该标准规定了一组最小的动作,所有符合标准的实现都必须以可预测的方式进行处理,除非它们遇到翻译限制(所有押注都无效)。它没有尝试定义实现必须支持以适合任何特定目的的所有动作。相反,对超出授权范围的行动的支持将被视为实施质量问题。作者承认,实现可能是合规的,但质量却很差,没有用。
诸如您这样的代码应该可用于旨在用于低级编程的高质量实现,并以预期的方式表示内存中的内容。不应期望它将在其他类型的实现中使用,包括那些将“实现质量”问题解释为试图以质量差但合规的方式行事的邀请。
答案 3 :(得分:-2)
将变量视为两种不同类型的安全方法是将其变为联合。联合的一部分可以是你的指针,另一部分是整数。
struct String
{
union
{
RealString*s;
int i;
};
};