Может ли указатель на неполный тип быть неполным? - PullRequest
9 голосов
/ 14 января 2020

Может ли int (*)[] быть неполным типом?

C 2018 6.2.5 1 говорит:

В различных точках в единице перевода тип объекта может быть неполное (недостаточно информации для определения размера объектов этого типа) или полное (достаточно информации).

Таким образом, представляется, что если размер типа известен, тип завершен. 6.2.6.1 28 указывает, что определенные типы указателей должны иметь одинаковые размеры (указатели на void и символы, указатели на совместимые типы, указатели на структуры и указатели на объединения), но указатели на другие типы могут различаться.

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

Как указывает MM , структура не должна содержать члена с неполным типом, за исключением последнего элемента гибкого массива, согласно ограничению в 6.7.2.1. 3. Это предполагает, что реализация с указателями одного размера должна принимать struct { int (*p)[]; }, тогда как реализация, имеющая разные размеры для таких массивов, должна диагностировать нарушение ограничения , (Это, в свою очередь, означает, что такая декларация не является частью строго соответствующего C.)

1 Ответ

3 голосов
/ 14 января 2020

Массив неизвестного размера является неполным:

Тип массива неизвестного размера - это неполный тип. Для идентификатора этого типа он завершается указанием размера в последующем объявлении (с внутренней или внешней связью).

Тип int (*)[], однако, не является неполным: это указатель на массив int неизвестного размера.
И указатель имеет хорошо известный размер:

printf ("Size %d\n", sizeof(int (*)[]));

6.2.5 / 23: тип имеет известный постоянный размер, если тип не является неполным и не является типом массива переменной длины.

Более того, вы даже можете разыменовать его, благодаря семантике массива:

typedef int (*T)[];
...
int a[10];
for (int i=0; i<10; i++) a[i]=i;
T p=a;
for (int i=0; i<10; i++) printf ("%d ",(*p)[i]);
printf ("\n");

Edit

In Кроме того, указатель всегда является полным типом. В 6.2.5 / 20 он написан черным по белому:

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

...