兼容类型与严格别名规则

Cha*_*l72 18 c

在C中将一种类型转换为另一种类型是一种常见的策略,依赖于C结构的布局具有某些保证的事实.像GLib这样的库依赖于它来实现面向对象的继承.基本上:

struct Base
{
  int x;
  int y;
};

struct Derived
{
  struct Base b;
  int z;
};
Run Code Online (Sandbox Code Playgroud)

这使得Base*指针可以分配给Derived对象的地址.

但我也知道" 严格别名 "规则,这是编译器隐含的假设,即不同类型的指针不能指向同一个地址.(这使编译器能够执行某些优化.)

那么,这两件事情如何协调?许多C库,包括Glib,CPython等,使用上述策略在类型之间进行转换.它们都只是用旗帜编译no-strict-aliasing吗?

Car*_*rum 20

在这种情况下,没有违反严格的别名. struct Derived 包含一个struct Base.语言标准明确允许这种行为.从C11 6.7.2.1结构和联盟说明者,第15段:

指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.

  • 如果struct`Endived`实际上不包含`struct Base`,但仅包含与`struct Base`相同的初始数据成员,那该怎么办?换句话说,如果`struct Derived`被定义为`struct Derived {int x; int y; int z; };` (3认同)
  • 那你可能有问题; 例如,编译器可能会选择使用不同的填充/打包特性. (3认同)
  • @ Channel72:C的类型系统(大部分)是名义上的,而不是结构上的,所以拥有相同的成员是不够的; 但是,有一个例外 - 联合中包含的结构的通用初始序列规则; 请注意,如果结构实际上不包含在这样的联合中,那么访问具有"错误"类型的结构在技术上仍然是未定义的行为(由于违反了有效的类型规则),即使编译器不能尽快采用严格的别名这样的联盟在范围内 (2认同)