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

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

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

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

这是正确的理解吗?

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

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

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

 int *pi; ... double *pd = static_cast(static_cast(pi)); 

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

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

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(pv); f(&d, pi); // assumption is violated 

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

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

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