Можно ли в C использовать указатели на массивы неполных типов?

Компилятор IAR Embedded C доволен этим, и я предположил, что это правильный код C:

struct incomplete;
typedef struct incomplete (*why_not)[2];
struct incomplete {struct incomplete *known_to_work;} array[2];
why_not ok = &array;

Однако gcc и clang задыхаются от определения why_not:

incomplete.c:2:29: error: array type has incomplete element type ‘struct incomplete’
 typedef struct incomplete (*why_not)[2];
                             ^

Технически нет причин отвергать определение типа «указатель на неполный массив». Ведь определение структуры нужно только там, где происходит разыменование такой переменной или выполняются какие-то арифметические операции с указателями.

Я стремлюсь скрыть определения структуры, где это возможно.

Что об этом говорит стандарт C?


person not-a-user    schedule 19.05.2017    source источник
comment
Вы не можете использовать массив типов неполного типа ни при каких обстоятельствах (даже параметры функции)   -  person M.M    schedule 19.05.2017
comment
@M.M На самом деле, почему бы и нет?   -  person not-a-user    schedule 19.05.2017
comment
Отправьте отчет об ошибке в IAR. Такое дерьмо - причина, по которой я не использую их компилятор. У них хватает духу требовать, чтобы вы платили им деньги, чтобы получать исправления их ошибок, связанных с несоблюдением требований. Это особенно смущает, поскольку эта часть C существует с 1980-х годов.   -  person Lundin    schedule 19.05.2017
comment
@ not-a-user, потому что так сказано в стандарте   -  person M.M    schedule 19.05.2017
comment
Я тестировал компилятор IAR ARM и получил предупреждение, но только при включенном строгом режиме.   -  person user694733    schedule 19.05.2017
comment
Это также нарушение ограничения в C по той же причине: struct S; void f(struct S s[]); , хотя void f(struct S *s); правильно, и было бы эквивалентно, если бы S был полным   -  person M.M    schedule 19.05.2017


Ответы (2)


В коде используется декларатор массива, где тип элемента неполный. Это нарушение ограничений в ISO C, согласно 6.7.6.2/1 Деклараторы массивов:

Ограничения

В дополнение к необязательным квалификаторам типа и ключевому слову static, [ и ] могут разделять выражение или *. Если они ограничивают выражение (которое определяет размер массива), выражение должно иметь целочисленный тип. Если выражение является постоянным выражением, оно должно иметь значение больше нуля. Тип элемента не должен быть неполным или функциональным.

person M.M    schedule 19.05.2017

Следующее утверждение

typedef struct incomplete (*why_not)[2];

указатель на массив из двух struct incomplete. Компилятор еще не знает размер struct incomplete, так как он еще не определен.

Однако следующее будет работать:

typedef struct incomplete *why_not[2];

то есть: массив указателей на struct incomplete. Компилятор знает размер указателя на неполный тип (т.е. это размер, необходимый для хранения адреса).


Изменить:

Компилятору не нужно знать размер struct incomplete в любом случае (пока не выполняется арифметика указателей), поскольку оба объявления просто объявляют указатели.

person 眠りネロク    schedule 19.05.2017
comment
Компилятор также знает размер указателя на массив неполного типа, который также является просто адресом. Как я уже говорил, есть по крайней мере один компилятор, который принимает это. Вопрос, что говорит стандарт (C99 или C11)? - person not-a-user; 19.05.2017
comment
Адреса объектов разных типов могут иметь разный размер (например, int * может быть 2 байта, а void * — 3 байта). - person M.M; 19.05.2017
comment
@M.M, в этом случае должно быть компилятор всегда знает размер указателя на неполный тип - person 眠りネロク; 19.05.2017