当CAN我打破别名规则?

时间:2012-03-19 19:11:05

标签: c++ strict-aliasing type-punning

我收到了这个警告。我想定义行为,但我想保持这个代码的原样。我什么时候可以打破别名规则?

  

警告:解除引用类型惩罚指针将破坏严格别名规则[-Wstrict-aliasing]

String是我自己的字符串,它是一个POD。此代码从C调用.S可能是int。字符串几乎是struct String { RealString*s; }但是模板和辅助函数。我做一个静态断言来确保String是一个pod,是4bytes,int是4bytes。我还写了一个断言,检查所有指针是否都是> = NotAPtr。它在我的新/ malloc重载。如果你建议

,我也可以将这个断言放在String中

考虑到我遵循的规则(主要是字符串是一个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
    }
}

4 个答案:

答案 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;
    };
};