C11 - преобразовать указатель на структуру в анонимный первый член структуры
Стандарт C гласит:
Указатель на объект структуры, соответствующим образом приведенный, указывает на его начальный элемент (или, если этот элемент является битовым полем, то на модуль, в котором он находится), и наоборот.
Есть ли какой-либо возможный (и четко определенный) способ выполнить такое "подходящее приведение" в C11, если первым членом рассматриваемой структуры является анонимная структура / объединение? Или выполнить обратное приведение "наоборот", если содержащая структура является анонимной?
Я предполагаю, что приведение к неанонимной структуре с той же последовательностью члена, что и для анонимной структуры, сделало бы это не очень четким, поскольку они несовместимы, и, следовательно, не гарантируется, что у них будет та же схема памяти.
Тем не менее, стандарт C гласит:
Кроме того, два типа структуры, объединения или перечисления, объявленные в отдельных единицах перевода, совместимы, если их теги и члены удовлетворяют следующим требованиям: если один объявлен с тегом, другой должен быть объявлен с тем же тегом. Если оба выполняются где-либо в пределах их соответствующих единиц перевода, то применяются следующие дополнительные требования: между их членами должна быть индивидуальная переписка <...>
Можем ли мы попытаться применить это правило к анонимным структурам? Скажем, если у нас есть следующие настройки:
header.h:
struct container {
struct {
int a;
char b;
};
};
void print(struct container *pcontainer);
sep.c:
#include <stdio.h>
#include "header.h"
void print(struct container *pcontainer){
printf("%d\n", ((struct { int a; char b; }*)pcontainer)->a);
}
main.c:
#include "header.h"
int main(void){
struct container container, *pcontainer;
pcontainer = &container;
pcontainer->a = 1;
print(pcontainer);
return 0;
}
(это компилируется в gcc (GCC) 4.8.3 20140911 и выводит 1).
Рассмотрим анонимную структуру, используемую в приведении внутри print
функция и анонимная структура, которая является первым членом struct container
что заканчиваетсяmain.c
, Могут ли они считаться "типами, объявленными в отдельных единицах перевода"? Кроме того, они действительно удовлетворяют всем другим требованиям совместимости, или я что-то неправильно понимаю?
1 ответ
Что такое переводческая единица:
5.1.1.1 Структура программы
- Программу A C не нужно переводить одновременно. Текст программы хранится в единицах, называемых исходными файлами (или файлами предварительной обработки) в этом международном стандарте. Исходный файл вместе со всеми заголовками и исходными файлами, включенными в директиву предварительной обработки #include, называется модулем преобразования предварительной обработки. После предварительной обработки блок преобразования предварительной обработки называется блоком перевода.
Таким образом, c-файл плюс заголовки после предварительной обработки образуют единое целое перевода. Давайте возьмем модуль перевода, который состоит из sep.c и header.h. Он содержит два объявления структуры struct { int a; char b; }
один в контейнере структуры, а другой в функции print. Эти структуры объявлены в той же единице перевода.
6.2.7 Совместимый тип и составной тип
- Два типа имеют совместимый тип, если их типы одинаковы. Дополнительные правила определения совместимости двух типов описаны в 6.7.2 для спецификаторов типов, в 6.7.3 для классификаторов типов и в 6.7.6 для деклараторов. Более того, два типа структуры, объединения или перечисления объявлены в отдельном переводе...
оставшийся текст относится к типам, объявленным в отдельных единицах перевода.
Поскольку структуры не объявляются в отдельных единицах перевода, они не подпадают под правило 6.2.7.
Поэтому в моей интерпретации структуры, одна в контейнере структуры, а другая в приведении в print(), несовместимы.