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

Ale*_*x B 18 c c++ gcc strict-aliasing

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

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

我想,const_caststatic_cast相关类型之间的演员阵容,因此他们是安全的,而reinterpret_cast可以打破严格走样规则.

这是正确的理解吗?

AnT*_*AnT 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));
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我仍然不确定是否可以在不破坏严格别名规则的情况下使用BSD套接字API的`sockaddr`相关部分. (4认同)
  • @Maister:不,使用联合在类型之间进行转换是未定义的行为.该标准仅允许从最后写入的联合的同一变量中读取. (4认同)
  • @caf:我相信BSD套接字API的sockaddr相关部分(以及在C中执行多态的任何其他API)实际上并没有违反严格别名,因为您可以通过"包含其中一个的聚合或联合类型"来访问其成员之间的上述类型(包括,递归地,子集合或包含联合的成员)",因此允许通过两个不同类型的结构指针访问`sa_family_t`类型的第一个字段. (4认同)
  • @ jons34yp - 另外,如果有两个结构的并集,那么标准也允许访问IIRC中的初始公共字段子序列. (2认同)