Почему пустой тип C не аналогичен пустому / нижнему типу?


28

Википедия, а также другие источники, которые я обнаружил в списке voidтипа C как тип единицы, а не пустой тип. Мне кажется, что это сбивает с толку, так как мне кажется, что оно voidлучше подходит под определение пустого / нижнего типа

  • voidНасколько я могу судить, ценности не обитают .
  • Функция с возвращаемым типом void указывает, что функция ничего не возвращает и, следовательно, может выполнять только некоторый побочный эффект.
  • Указатель типа void*является подтипом всех других типов указателей. Кроме того, преобразования в и из void*в C являются неявными.

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

С другой стороны, voidсам по себе не является подтипом всех других типов, что, насколько я могу судить, является требованием, чтобы тип был нижним типом.


10
Под «не возвращает ничего» вы на самом деле подразумеваете «не возвращает ничего интересного», тогда как функция с пустым выводом не возвращает вообще (т. Е. Аварийно завершает работу или циклически повторяется).
Турион

2
В качестве возвращаемого типа void является типом блока.
user253751

Ответы:


38

В C voidиспользуется для нескольких несвязанных вещей. В зависимости от того, для чего он используется, его значением может быть тип единицы, пустой тип или что-то еще.

voidvoid*void020=1

Это не пустой тип: функция, которая возвращает пустой тип, не может возвращать значение, так как нет значения этого типа. Функция с возвращаемым пустым типом может только зацикливаться навсегда, или прерывать программу, или вызывать исключение ( longjmp) (или иначе договариваться о невозможности возврата, например, путем передачи управления другому потоку или процессу с использованием функциональных возможностей, выходящих за рамки стандартного C). Чтобы сбить с толку, в C принято использовать voidвместо пустого типа (C не имеет пустого типа).

void0voidvoidreturnvoidvoid

C не имеет нижнего типа в смысле разрешения любого возможного типа. Даже неполные типы определяют общую природу его значений, например указателей или структур, объединений или функций. Но void*это указатель на любой нефункциональный тип: это наименьший элемент алгебры типов указателей на объекты, т.е. это нижний тип указателя на объект. В отличие от общего случая, T*где Tиспользуется некоторый тип, отличный от void, void*это не тип указателей на значение типа void, а тип указателей на значение неопределенного типа.


Можно вернуть void в C ++ и C89. stackoverflow.com/questions/35987493/…
BartekChom

2
Четвертый абзац формально неверен. В C объем хранилища для voidнеопределен, а не ноль. Это не причина, почему объекты типа voidзапрещены. Формальная причина в том, что voidэто неполный тип , и объекты не могут иметь неполный тип.
MSalters

4
@MSalters Нет, то, что я написал, формально правильно. «Потому что» относится к мотивации дизайна языка, а не к логическим выводам в спецификации языка. voidТипа требует 0 бит хранения. Это причина, по которой разработчики C решили создать voidнеполный тип, в отличие от определения, что он занимает 0 байт памяти (что будет иметь большое влияние на структуру языка) или 1 байт памяти (что приведет к потере места). ,
Жиль "ТАК - перестань быть злым"

1
@ Жиль: Извините, но это тоже не имеет смысла. Если разрешено, используемое пространство будет 1 байт на объект типа void , и вам, очевидно, не нужно много объектов 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.