Может 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.)
источник
void *
завершено, показывает, что указатель на неполный тип может быть завершен. Он не показывает, может ли указатель на неполный тип быть неполным. Если бы кто-то спросил: «Может ли млекопитающее быть слоном?», Показ того, что «Лев - это млекопитающее», не означает, что млекопитающее не может быть слоном. Вопрос состоит в том, может ли множество указателей X иметь неполный тип и содержать элемент, который является неполным. Показывать, что множество X указателей на неполный тип содержит полный элемент, не имеет значения.Ответы:
Массив неизвестного размера является неполным:
Тип,
int (*)[]
однако, не является неполным: это указатель на массивint
неизвестного размера.И указатель имеет хорошо известный размер:
Более того, вы даже можете разыменовать его, благодаря семантике массива:
редактировать
Кроме того, указатель всегда является полным типом. В 6.2.5 / 20 написано черным по белому:
источник
printf
только показывает, что указатель на неполный массив завершен в реализации, в которой он был выполнен, как указано в вопросе - если бы не было 6.2.5 20, процитированного в последнем абзаце, он мог бы не скомпилироваться. 6.2.5 23 тоже не актуально; он говорит нам, что размер известен и постоянен, если он завершен, и мы уже знаем, что значение «полный» означает, что размер известен.int
должны иметь одинаковый размер, а все указатели на массивы определенногоstruct
размера должны иметь одинаковый размер, хотя, возможно, не все указатели на массивы различных типовstruct
должны иметь одинаковый размер. как друг друга.T(*)[]
они имели одинаковый размерT(*)[5]
, так как они являются совместимыми типами, и мы можем добавлять или удалять квалификаторы