Совместимые типы и строгие правила псевдонимов

Это общая стратегия в C, чтобы наложить один тип на другой тип, полагаясь на то, что макет структуры C имеет определенные гарантии. Библиотеки, такие как GLib, полагаются на это, чтобы реализовать объектно-ориентированное наследование. В основном:

struct Base
{
  int x;
  int y;
};

struct Derived
{
  struct Base b;
  int z;
};

Это позволяет привязать указатель Base* к адресу объекта Derived.

Но я также знаю правило < строгое псевдонижение", которое является неявным предположением компилятора о том, что разные типы указатели не могут указывать на один и тот же адрес. (Это позволяет компилятору выполнить определенные оптимизации.)

Итак, как эти две вещи примирились? Многие библиотеки C, включая Glib, CPython и т.д., Используют приведенную выше стратегию для различения типов. Все они просто компилируются с такими флагами, как no-strict-aliasing?

Ответы

Ответ 1

В этом случае нет строгого сглаживания. struct Derived содержит a struct Base. Этот тип поведения явно разрешен стандартом языка. От C11 6.7.2.1 Спецификаторы структуры и объединения, пункт 15:

Указатель на объект структуры, соответствующим образом преобразованный, указывает на его исходный элемент (или если этот элемент является битовым полем, а затем в единицу, в которой он находится) и наоборот.