C ++中的C99严格别名规则(GCC)

时间:2010-05-05 06:25:53

标签: c++ c gcc strict-aliasing

据我了解,GCC支持C ++中的所有C99功能。但是如何在C ++代码中处理C99严格别名?

我知道在不相关的类型之间使用C转换进行转换不是严格别名安全的,并且可能生成错误的代码,但是C ++呢?由于严格别名不是C ++标准的一部分(这是正确的吗?),GCC必须自己指定语义。

我在相关类型之间投射const_caststatic_cast,因此它们是安全的,而reinterpret_cast可以打破严格的别名规则。

这是正确的理解吗?

3 个答案:

答案 0 :(得分:31)

不,你可能会混合不同的东西。

严格的别名规则与C99标准完全无关。自[标准化]时间开始以来,严格的别名规则植根于C和C ++中存在的标准部分。禁止通过另一种类型的左值访问一种类型的对象的条款存在于C89 / 90( 6.3 )以及C ++ 98中( 3.10 / 15 )。这就是严格的混淆,不多也不少。只是并非所有编译器都希望(或敢于)强制执行或依赖它。 C和C ++语言有时被用作“高级汇编”语言,严格的别名规则经常会干扰这些用法。 GCC做出了大胆的举动,并决定在优化过程中开始依赖严格的别名规则,经常从那些“汇编”类型中吸引投诉。

确实,在C ++中打破严格别名规则的最简单方法是reinterpret_cast(当然还有C风格的转换)。但是,static_cast也可以用于此目的,因为它允许通过在“链式”强制转换中使用void *作为中间类型来打破严格别名

int *pi;
...
double *pd = static_cast<double *>(static_cast<void *>(pi));

const_cast无法在兼容的编译器中破坏严格的别名。

至于C99 ...... C99所做的是restrict限定词。这与别名直接相关,但它本身并不是所谓的严格别名。

答案 1 :(得分:4)

static_cast也可以破坏别名规则,因为编译器信任您以确保目标类型与对象的实际运行时类型相关。考虑:

extern void f(double*, int*); // compiler may optimize assuming that arguments don't overlap
double d;
void* pv = &d;
int* pi = static_cast<int*>(pv);
f(&d, pi); // assumption is violated

答案 2 :(得分:2)

Cpp的概念是一样的;因为您可以使用C样式转换来指导您完成严格别名的安全性。

简而言之:不,使用Cpp铸造(您已经概述过)的方法不能安全地涵盖所有情况。打破规则的一种常见方法是使用static_cast来转换指针。

只需打开编译器警告 - 它会(或应该)告诉你什么是不安全的。