C 2018 6.7.6.2 1 определяет ограничения для деклараторов массива.В нем говорится, частично:
Тип элемента не должен быть неполным или функциональным.
В Map (*ps)[16]
, (*ps)[16]
представляет собой объявлений , как показано в грамматике в 6.7.6 1. Поскольку это декларатор массива, он подчиняется правилам в 6.7.6.2, и поэтому тип элемента должен быть завершен.Это верно, даже если объявленный типовой тип является указателем.
Как отмечено в комментарии, вы можете объявить Map *ps
вместо этого.Если это неудовлетворительно, потому что тогда арифметика указателей на ps
работает в единицах Map
вместо Map [16]
, альтернативой может быть определение typedef struct Map16 Map16;
перед объединением, затем Map16 *ps;
внутри объединения, а затем struct Map16 { Map element[16]; }
после объединения.Это заставит арифметику указателя на ps
работать в нужных единицах (предположим, что реализация не дополняет структуру, что было бы необычно), хотя она и заставляет использовать дополнительный .element
при обращении к элементам.
Рассматривая, почему Map *ps
принимается, а Map (*ps)[16]
нет, мы видим, что оба объявляют указатели на неполные типы, и поэтому их отличает не полнота указательного типа, а просто это правило в Cстандарт.Может случиться так, что правило в 6.7.6.2 1 могло быть изменено для разрешения Map (*ps)[16]
, так как не похоже, что компилятору требуется полная информация о указанном типе в этой точке.