Получает ли доступ к первому полю структуры с помощью C cast нарушает строгий псевдоним?

Нарушает ли этот код строгий псевдоним?

struct {int x;} a;
*(int*)&a = 3

Более абстрактно, является ли законным применять разные типы до тех пор, пока примитивные операции чтения/записи правильны?

Ответы

Ответ 1

Во-первых, это законно применять в C. §6.7.2.1/13:

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

Правило псевдонимов гласит следующее (§6.5/7):

Объект должен иметь сохраненное значение, доступ к которому имеет только выражение lvalue, которое имеет один из следующие типы:

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

Здесь вы можете получить доступ к нему с помощью указателей типа, совместимого с эффективным типом объекта, и "совокупного или унифицированного типа, который включает один из вышеупомянутых типов среди его членов", поэтому никаких проблем с псевдонимом тоже нет. Таким образом, в C действительно совершенно легально получить доступ к первому члену структуры, указав указатель на структуру на тип рассматриваемого элемента.

В С++, однако, вы часто найдете vtables и другие вещи в начале объекта С++. В вашем конкретном случае, однако, ваша структура имеет стандартный макет, и поэтому это явно разрешено (§9.2/20 в n3290, спасибо Люку Дантону! - С++ 03, по-видимому, имеет аналогичное правило, выраженное в терминах объектов POD).