При разработке интерфейса C обычно допускается в публичный интерфейс (.h
) только то, что должно быть известно пользовательской программе.
Следовательно, например, внутренние компоненты структур должны оставаться скрытыми, если пользовательская программа не нуждается в них. Это действительно хорошая практика, так как контент и поведение структуры могут измениться в будущем, не затрагивая интерфейс.
Отличным способом достижения этой цели является использование неполных типов.
typedef struct foo opaqueType;
Теперь можно создать интерфейс, содержащий только указатели на opaqueType
, без пользовательской программы, когда-либо требующей знать внутреннюю работу struct foo
.
Но иногда может потребоваться распределение такой структуры статически, как правило, в стеке, для проблем с производительностью и фрагментацией памяти. Очевидно, что при построении выше opaqueType
является неполным, поэтому его размер неизвестен, поэтому его нельзя статически распределять.
Обходной задачей является выделение "типа оболочки", например:
typedef struct { int faketable[8]; } opaqueType;
Над конструкцией применяется размер и выравнивание, но не идет дальше в описание того, что действительно содержит структура. Таким образом, он соответствует цели сохранения типа "непрозрачный".
В основном это работает. Но в одном случае (GCC 4.4) компилятор жалуется, что он нарушает строгое сглаживание и генерирует багги-двоичный файл.
Теперь я прочитал массу вещей о строгом псевдониме, поэтому, я думаю, теперь я понимаю, что это значит.
Возникает вопрос: существует ли способ определить непрозрачный тип, который тем не менее может быть выделен в стеке, и не нарушая строгое правило сглаживания?
Обратите внимание, что я попытался использовать метод union, описанный в этой замечательной статье, но он все равно генерирует такое же предупреждение.
Обратите внимание, что визуальные, clang и gcc 4.6 и более поздние не жалуются и отлично работают с этой конструкцией.
[Изменить] Информация дополняет:
Согласно испытаниям, проблема возникает только при следующих обстоятельствах:
- Частный и открытый тип. Я делаю публичный тип приватным внутри файла
.c
. Не имеет значения, если они являются частью одного и того же союза. Не имеет значения, содержит ли открытый типchar
. - Если все операции с закрытым типом просто читаются, проблем нет. Только записи вызывают проблемы.
- Я также подозреваю, что только функции, которые автоматически встроены, попадают в неприятности.
- Проблема возникает только при gcc 4.4 при настройке -O3. -O2 в порядке.
Наконец, моя цель - C90. Может быть, C99, если на самом деле нет выбора.