Чи може вказівник на неповний тип бути неповним?


9

Може int (*)[]бути неповним типом?

C 2018 6.2.5 1 каже:

У різних точках в одиниці перекладу тип об'єкта може бути неповним (бракує достатньої інформації для визначення розміру об'єктів цього типу) або повним (має достатню інформацію).

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

У застосуванні C, де всі вказівники або всі вказівники на масиви intмають однаковий розмір, тоді розмір int (*)[]відомий, тому він був би повним. У реалізації, яке, скажімо, використовує різні покажчики для великих масивів, розмір не буде відомий, тому він є неповним.

Як зазначає ММ , структура не повинна містити члена з неповним типом, за винятком остаточного гнучкого члена масиву, за обмеженням в 6.7.2.1 3. Це говорить про те, що реалізація з одним розміром покажчиків повинна приймати, struct { int (*p)[]; }тоді як реалізація має інший розміри для таких масивів повинні діагностувати порушення обмеження. (Це в свою чергу означає, що така декларація не є частиною суворої відповідності С.)


6.2.5 (p22) допомога? (чи додає це ще більше плутанини, що дозволяє завершити неповний тип подальшим декларуванням?)
Девід С. Ранкін

@ DavidC.Rankin У 6.2.5 / 20 навіть сказано, що покажчики завжди є повноцінними типами
Крістоф,

@LanguageLawyer: Наскільки це може бути доречно? Питання "Чи існує X, який не є Y?", А не "Чи є X, який є Y?"
Eric Eric Postpischil

@LanguageLawyer: Повний факт void *свідчить про те, що вказівник на неповний тип може бути повним. Це не показує, чи може вказівник на неповний тип бути неповним. Якщо хтось запитав: «Чи може ссавець бути слоном?», Показуючи, що «Лев - ссавець», це не означає, що ссавець не може бути слоном. Питання задає питання, чи може множина X покажчиків на неповний тип містити неповний елемент. Показати, що набір X покажчиків на неповний тип містить елемент, який є повним, не має значення.
Ерік Postpischil

@EricPostpischil На жаль Я неправильно прочитав заголовок як "Чи може вказівник на неповний тип бути повним ?"
юрист з мови

Відповіді:


3

Масив невідомого розміру є неповним:

Тип масиву невідомого розміру - неповний тип. Він завершений для ідентифікатора цього типу, вказавши розмір у більш пізній декларації (із внутрішнім чи зовнішнім зв’язком).

Однак тип 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");

Редагувати

Крім того, вказівник завжди є повним типом. Це написано чорно-білим кольором в 6.2.5 / 20:

Тип вказівника може бути похідний від типу функції або типу об'єкта, який називається посилальним типом. Тип вказівника описує об'єкт, значення якого надає посилання на сутність типу посилання. Тип вказівника, похідний від посиланого типу T, іноді називається "вказівником на T". Побудова типу вказівника з посилального типу називається '' виведенням типу вказівника ''. Тип вказівника - це повний тип об'єкта.


Я думаю, ви це зварили і gcc погоджується. struct w / покажчик на неповний масив схожий на початкове запитання, що спонукає до дискусії.
Девід К. Ранкін

Має значення лише останній абзац. Приклад printfлише показує, що вказівник на неповний масив є завершеним в реалізації, в якій він був виконаний, як зазначено в запитанні - якби не 6.2.5 20, процитований в останньому абзаці, він не міг би компілюватись. 6.2.5 23 також не стосується; це говорить нам, що розмір відомий і постійний, якщо він повний, і ми вже знаємо, що бути повним означає, що розмір відомий.
Eric Eric Postpischil

6.2.5 20 цікаво. Я припускаю, що це не було наслідком цього, але це означає, що всі покажчики на завершення типів, які мають один і той же тип, коли неповні, повинні мати однаковий розмір. Наприклад, всі вказівники на масиви intповинні мати однаковий розмір один до одного, а всі вказівники на масиви певних structповинні мати однаковий розмір один з одним, хоча, можливо, не всі вказівники на масиви різних видів structповинні мати однаковий розмір як один одного.
Eric Eric Postpischil

1
@EricPostpischil, можливо, текст "Аналогічно, покажчики на кваліфіковані або некваліфіковані версії сумісних типів повинні мати однакові вимоги щодо представлення та вирівнювання." слід тлумачити, що вони T(*)[]повинні мати однаковий розмір T(*)[5], оскільки вони є сумісними типами, і ми могли б додавати або видаляти класифікатори
ММ

Дозвіл сумісних типів мати різні розміри призведе до цілого ряду проблем, можливо, дефект у тому, що стандарт явно не виключає цього
MM
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.