Чому тип пустоти C не є аналогом типу порожній / нижній?


28

Вікіпедія, а також інші джерела, які я знайшов, перелічують voidтип C як тип одиниці, а не порожній. Я вважаю це заплутаним, як мені здається, що voidкраще відповідає визначенню типу порожній / нижній.

  • voidНаскільки я можу сказати, цінності не населяються .
  • Функція з типом повернення void вказує, що функція нічого не повертає і, таким чином, може виконувати лише деякі побічні ефекти.
  • Вказівник типу void*- це підтип усіх інших типів вказівника. Крім того, конверсії в та з void*в C є неявними.

Я не впевнений, чи є останній пункт якоюсь заслугою як аргументом voidтого, що він є порожнім типом, як void*це більш-менш окремий випадок, який не має особливого відношення до void.

З іншого боку, voidсам по собі не є підтипом усіх інших типів, що, наскільки я можу сказати, є вимогою до типу, який має нижній тип.


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

2
Як тип повернення, void - це тип одиниці.
користувач253751

Відповіді:


38

В C voidвикористовується для безлічі непов'язаних речей. Залежно від того, для чого він використовується, його значення може бути тип одиниці, порожній тип чи щось інше.

Коли voidвикористовується сам (на відміну від void*вказівника на недійсність), це тип одиниці, тобто тип з єдиним значенням. Функції, які повертаються void, кажуть, що "нічого не повертають", але те, що це насправді означає, це те, що вони не повертають жодної інформації. Вони повертають біт інформації, це означає, що вони повертають значення типу, що містить різних значень, тобто тип одиниці.2 0 = 1020=1

Це не порожній тип: функція, яка повертає порожній тип, не може повернути значення, оскільки значення цього типу немає. Функція, тип повернення якої порожній, може циклічно фіксувати лише назавжди, або скасовувати програму, або підняти виняток ( longjmp) (або іншим чином домовитись не повертатись, наприклад, перенести управління на інший потік або обробити, використовуючи функціонал, що перевищує стандартний C). Щоб не переплутати речі, звичайно в C використовувати voidзамість порожнього типу (C не має порожнього типу).

Для цього voidтипу потрібно біт пам’яті. Оскільки C наполягає на тому, що кожен об'єкт займає ціле, ненульове число байтів сховища, створювати об’єкт типу заборонено , а для повернення значення є спеціальний синтаксис ( вислів зі значенням опущеним). Немає синтаксису, який дає значення типу , але це значення є, коли функція, тип повернення якої є, повертається.0voidvoidreturnvoidvoid

C не має нижнього типу в тому сенсі, що дозволяє будь-який можливий тип. Навіть неповні типи визначають загальний характер її значень, наприклад, покажчики або структури, об'єднання чи функції. Але void*є вказівником на будь-який нефункціональний тип: це найменший елемент алгебри типів об’єктних вказівників, тобто тип нижнього об'єкта. На відміну від загального випадку, T*коли Tє якийсь недійсний тип, void*це не тип покажчиків на значення типу void, а тип покажчиків на значення не визначеного типу.


Можна повернути недійсність у C ++ та C89. stackoverflow.com/questions/35987493 / ...
BartekChom

2
4-й абзац формально неправильний. У C обсяг пам’яті для voidне визначений, а не нульовий. Це не є причиною voidзаборони об’єктів типу . Формальна причина полягає в тому, що voidце неповний тип , а об'єкти не можуть мати неповний тип.
MSalters

4
@MSalters Ні, те, що я написав, формально правильно. "Тому що" відноситься до мотивації мовної конструкції, а не до логічних висновків всередині мовної специфікації. Для цього voidтипу потрібно 0 біт пам’яті. Це причина, чому дизайнери C вирішили зробити voidнезавершений тип, на відміну від визначення його, займаючи 0 байтів пам’яті (що мало б великий вплив на мовну конструкцію) або 1 байт сховища (який би витрачав місце) .
Жил "ТАК - перестань бути злим"

1
@Gilles: Вибачте, але і це не має сенсу. Якщо це дозволено, простір, що використовується, складе 1 байт на об'єкт недійсного типу , і вам, очевидно, не потрібно багато об’єктів voidтипу. Не кажучи вже про те, що ці об’єкти можуть мати псевдоніми всі інші об'єкти, тому фактичне використання все одно буде нульовим.
MSalters

4
@CodesInChaos: Ну, C ++ фактично дозволяє пусті структури, тобто struct E { };. Якщо він використовується як базовий клас, він може бути нульовим розміром. (Насправді немає такого поняття, як C / C ++, обидві мови роблять власний вибір, і вони можуть відрізнятися в цих областях. C явно не має порожніх базових класів, оскільки в першу чергу немає ОО)
MSalters

11

Назва "порожній тип", можливо, заплутана. Це означає, що, як ви самі кажете, тип не містить значень . "Порожній" означає не будь-які окремі значення типу, він відноситься до типу в цілому, розглядається як ~ набір можливих значень. Так що це НЕ що - щось на зразок «функції не повертаючи voidповертає ніякої інформації», але « не існує ніякого значення типу ».

Це означає, що функція, тип результату якої ніколи не може бути припинена. Якщо б воно припинилося, якщо б довелося повернути значення , але, ну, такого значення не існує.

Це також означає, що навіть неможливо обговорити, скільки інформації містило б значення порожнього типу, оскільки такого значення немає. (Або, якщо ви хочете, безглузде твердження на кшталт "будь-яке значення порожнього типу містить точно 35093658 біт інформації" є нечистою правдою.) Дещо корисно (хоча і не дуже правильно) думати про значення як такі, що містять нескінченну кількість інформації.

Тоді як функція C із "типом повернення" voidявно може повернутись, але не дає ніякої інформації про її повернене значення. Ну, саме це характеризує тип одиниці: його значення не містять жодної інформації, оскільки є лише одне таке значення (отже, ви завжди можете сказати, яким буде повернене значення, навіть не намагаючись коли-небудь викликати функцію).

Щоб цитувати Конора Макбрайда (транслітерований на C):

voidозначає «Нудно». Це означає нудний тип, який містить одне, також нудне. Нічого цікавого не можна отримати, порівнюючи один елемент нудного типу з іншим, тому що нічого не можна дізнатися про елемент нудного типу, надаючи йому будь-яку вашу увагу.

Він сильно відрізняється від порожнього типу [...]. Порожній тип дуже захоплюючий, тому що якщо хтось коли-небудь надає вам належне йому значення, ви знаєте, що ви вже мертві і на Небі, і все, що ви хочете, - це ваше.


Цікаво; якщо визначення ⊥ є функцією, тип повернення якої ⊥ ніколи не може закінчитися, тоді C має такий тип. Ми називаємо це мінливою порожнечею.
Джошуа

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