当我可以打破混叠规则

When CAN i break aliasing rules?

本文关键字:规则 我可以      更新时间:2023-10-16

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

警告:取消引用类型punned指针将破坏严格的别名规则[-Wstrict aliasing]

字符串是我自己的字符串,它是POD。这段代码是从C调用的。S可能是一个int。字符串几乎是struct String { RealString*s; },但却是模板化的和辅助函数。我做了一个静态断言,以确保String是一个pod,是4字节,int是4字节。我还写了一个断言,它检查所有指针是否都是>=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
    }
}
完全支持

memcpy。对char*的双关语也是如此(例如,您可以使用std::copy)。

如果您不能按照建议将代码更改为2个函数,为什么不呢(需要C99编译器,因为它使用uintptr_t-对于较旧的MSVC,您需要自己定义它,2008/2010应该可以):

void f(RealString *s) {
    uintptr_t int = reinterpret_cast<uintptr_t>(s);
    assert(int);
}

标准指定了一组最小的操作,所有符合要求的实现都必须以可预测的方式处理这些操作,除非它们遇到翻译限制(因此所有赌注都被取消)。它并不试图定义实现必须支持的所有操作,以适合任何特定目的。相反,对超出授权范围的行动的支持被视为执行质量问题。作者承认,一个实施可能是符合要求的,但质量太差,以至于毫无用处。

像您这样的代码应该可用于用于低级别编程的高质量实现,并且以预期的方式表示内存中的内容。它不应该被期望用于其他类型的实现,包括那些将"实现质量"问题解释为邀请人们尝试以低质量但符合要求的方式行事的实现。

将变量视为两种不同类型的安全方法是将其转换为并集。并集的一部分可以是指针,另一部分是整数。
struct String
{
    union
    {
        RealString*s;
        int i;
    };
};