Указатель на массив непрозрачных структур

У меня есть странная проблема с gcc 4.3, и я хотел знать, является ли это конкретной проблемой с компилятором или это общая проблема C. Конечно, я использую очень странную конструкцию, но она мне нравится, потому что она позволяет мне применять некоторые правила, которые в противном случае были бы невозможны. Проект разделен на несколько модулей, и каждый модуль имеет непрозрачную структуру. В заголовке есть объявление typedef struct <tag> <type>, а в 1 файле c есть struct tag { ... };, и все функции ссылаются на элемент через <type> *.

Каждый модуль знает свою структуру, структуры других модулей не видны. В одном модуле я работаю не с 1 элементом, а с фиксированным массивом элементов. Это означает, что некоторые функции этого модуля работают с указателем на массив. Назовем этот модуль wdi. Так у меня например

void write_all(wdi_type (*wdis)[MAX_WDI]);

а для размещения (знаю очень необычный синтаксис) возвращать прямо правильный указатель на массив.

wdi_type (*wdi_alloc(void))[MAX_WDI];

Это хорошо работает под GNU-C 3.4.6 (Solaris SPARC), под cc, компилятором sun v12, который он также компилирует (не удалось проверить, потому что другая часть приложения ломается). Однако на gcc 4.3.3 (также тестировалось на 4.4.6 x86-64 и 4.6.2 ARM) это не так. Я получаю ошибку компиляции array type has incomplete element type. Я не понимаю, зачем компилятору нужна эта информация на этом этапе. Ему также не нужен размер других непрозрачных структур.

Это ошибка gcc?

Что говорит стандарт?

Я не смог найти что-то об этом. Должен ли я подать отчет об ошибке в GNU?


person Patrick Schlüter    schedule 09.04.2013    source источник


Ответы (1)


Стандарт (ну, проект N1570 стандарта C2011) говорит, в 6.2.5 (20)

Тип массива описывает непрерывно выделенный непустой набор объектов с определенным типом объекта-члена, называемым типом элемента. Тип элемента должен быть полным всякий раз, когда указывается тип массива.

(выделено мной)

Соответствующий отрывок в стандарте C99 был менее убедительным:

Тип массива описывает непрерывно размещенный непустой набор объектов с определенным типом объекта-члена, называемым типом элемента.36)

36) Поскольку типы объектов не включают неполные типы, массив неполных типов не может быть создан.

он не запрещал явно указывать тип массива для неполного типа элемента, а только конструировал такой массив.

Мне не удалось выяснить, когда и почему сноска 36 была заменена выделенным предложением, но это было до ноябрь 2010 г..

Казалось бы, gcc-4.x отклоняет код на основе новой версии, а gcc-3.4.6 принимает его на основе более старой версии, поэтому я не думаю, что это ошибка, и код явно недействителен согласно к действующему стандарту.

person Daniel Fischer    schedule 09.04.2013
comment
Спасибо, я так и думал. Мне придется изменить свой код. Жаль, так было намного безопаснее, используя обычный wdi_type * вместо wdi_type (*wdis)[MAX_WDI] компилятор теряет одну информацию для проверки типа. - person Patrick Schlüter; 10.04.2013