Dlaczego typ pustki C nie jest analogiczny do typu pusta / dolna?

28

Wikipedia, jak również inne źródła, które znalazłem, wskazują voidtyp C jako typ jednostki, a nie typ pusty. Uważam to za mylące, ponieważ wydaje mi się, że voidlepiej pasuje do definicji typu pustego / dolnego.

  • voidO ile wiem, nie zamieszkują żadnych wartości .
  • Funkcja z typem zwracanym void określa, że ​​funkcja nic nie zwraca, a zatem może wywołać tylko pewien efekt uboczny.
  • Wskaźnik typu void*jest podtypem wszystkich innych typów wskaźników. Również konwersje do iz void*C są niejawne.

Nie jestem pewien, czy ostatni punkt ma jakąkolwiek wartość jako argument za voidbyciem pustym typem, ponieważ void*jest to mniej więcej szczególny przypadek z niewielkim stosunkiem void.

Z drugiej strony voidsam nie jest podtypem wszystkich innych typów, co, o ile wiem, jest wymogiem, aby typ był typem dolnym.

Meta
źródło
10
Przez „nie zwraca niczego” masz na myśli „nie zwraca niczego interesującego”, podczas gdy funkcja z pustym wyjściem w ogóle nie zwraca (tj. Zawiesza się lub zapętla nieskończenie).
Turion,
2
Jako typ zwrotu void jest typem jednostki.
user253751,

Odpowiedzi:

38

W C voidjest używany do wielu niepowiązanych rzeczy. W zależności od tego, do czego jest używany, może to oznaczać typ jednostki, typ pusty lub coś innego.

Gdy voidjest używany samodzielnie (w przeciwieństwie do void*wskaźnika do pustki), jest to typ jednostki, tj. Typ z jedną wartością. voidMówi się, że funkcje, które zwracają , „nic nie zwracają”, ale tak naprawdę oznacza to, że nie zwracają żadnych informacji. Zwracają bitów informacji, co oznacza, że ​​zwracają wartość typu, który zawiera odrębne wartości, tj. Typ jednostki.020=1

To nie jest pusty typ: funkcja zwracająca pusty typ nie może zwrócić wartości, ponieważ nie ma żadnej wartości tego typu. Funkcja, której typ zwracany jest pusty, może zapętlać na zawsze, przerywać program lub zgłaszać wyjątek ( longjmp) (lub w inny sposób zapewniać brak powrotu, np. Poprzez przeniesienie kontroli do innego wątku lub procesu przy użyciu funkcjonalności wykraczającej poza standardowy C). Aby utrzymać zamieszanie, w C zwykle używa się voidzamiast pustego typu (C nie ma pustego typu).

voidTen wymaga bitów przechowywania. Ponieważ C nalega, aby każdy obiekt zajmował całą niezerową liczbę bajtów pamięci, zabronione jest tworzenie obiektu typu i istnieje specjalna składnia zwracająca wartość ( instrukcja z pominiętą wartością). Nie ma składni, która daje wartość typu , ale ta wartość jest dostępna za każdym razem, gdy zwraca funkcję, której typ zwracany jest .0voidvoidreturnvoidvoid

C nie ma typu dolnego w tym sensie, że dopuszcza dowolny możliwy typ. Nawet niekompletne typy określają ogólny charakter jego wartości, np. Wskaźniki, struktury, związki lub funkcje. Ale void*jest wskaźnikiem do każdego typu non-funkcyjny: to najmniejszy element algebry typów obiektów wskaźnik, czyli jest to dolna typ obiektu wskaźnik. W przeciwieństwie do ogólnego przypadku T*, gdzie Tjest jakiś zakaz typ void, void*nie jest typem wskaźników do wartości typu void, ale rodzaj wskaźników do wartości nieokreślonego typu.

Gilles „SO- przestań być zły”
źródło
Void można przywrócić w C ++ i C89. stackoverflow.com/questions/35987493/…
BartekChom
2
Czwarty akapit jest formalnie błędny. W C ilość pamięci dla voidjest niezdefiniowana, a nie zero. To nie jest powód, dla którego obiekty typu voidsą niedozwolone. Formalne Powodem jest to, że voidjest niekompletny typ , a obiekty nie mogą mieć niekompletną typu.
MSalters,
4
@MSalters Nie, to, co napisałem, jest formalnie poprawne. „Ponieważ” odnosi się do motywacji projektowania języka, a nie do logicznych wniosków w specyfikacji języka. voidTypu wymaga bitów 0 składowania. To jest powód, dla którego projektanci C postanowili stworzyć voidniekompletny typ, w przeciwieństwie do zdefiniowania, że ​​zajmuje on 0 bajtów pamięci (co miałoby duży wpływ na projekt języka) lub 1 bajt pamięci (co marnowałoby miejsce) .
Gilles „SO- przestań być zły”
1
@Gilles: Przepraszam, ale to też nie ma sensu. Jeśli jest to dozwolone, używana przestrzeń będzie wynosić 1 bajt na obiekt typu pustki i oczywiście nie potrzebujesz wielu obiektów voidtypu. Nie wspominając o tym, że te obiekty mogłyby aliasować wszystkie inne obiekty, więc faktyczne użycie i tak wyniesie zero.
MSalters,
4
@CodesInChaos: C ++ faktycznie pozwala na puste struktury, tj struct E { };. W przypadku użycia jako klasy bazowej może mieć rozmiar zero. (Naprawdę nie ma czegoś takiego jak C / C ++, dwa języki dokonują własnych wyborów i mogą się różnić w tych obszarach. C oczywiście nie ma pustych klas podstawowych, ponieważ nie ma OO w pierwszej kolejności)
MSalters
11

Nazwa „pusty typ” może być myląca. Oznacza to, jak sam twierdzisz, że typ nie zawiera żadnych wartości . „Pusty” nie odnosi się do żadnych indywidualnych wartości typu, odnosi się do typu jako całości, traktowanego jako zbiór możliwych wartości. Więc to nie nie powiedzieć coś w stylu „funkcja powrocie voidnie zwraca informacji”, ale „nie istnieje żadnej wartości typu ”.

Oznacza to funkcję, której typ wyniku nigdy nie może zostać zakończony. Gdyby się skończyło, musiałbym zwrócić wartość , ale cóż, taka wartość nie istnieje.

Oznacza to również, że nie można nawet omówić, ile informacji zawiera wartość pustego typu, ponieważ nie ma takiej wartości. (Lub, jeśli wolisz, bezsensowne stwierdzenie, takie jak: „każda wartość pustego typu zawiera dokładnie 35093658 bitów informacji” jest bez wątpienia prawdziwe.) Przydatne (choć niezupełnie poprawne) jest myślenie o wartościach zawierających nieskończoną ilość informacji.

Podczas gdy funkcja C z „typem zwrotu” voidwyraźnie może zwrócić, ale nie daje żadnych informacji w jej wartości zwracanej. Cóż, właśnie to charakteryzuje typ jednostki: jego wartości nie zawierają żadnych informacji, ponieważ istnieje tylko jedna taka wartość (stąd zawsze możesz powiedzieć, jaka będzie wartość zwracana, nawet bez zawracania głowy wywołaniem funkcji).

Cytując Conora McBride'a (w transliteracji do C):

voidoznacza „nudne”. Oznacza nudny typ, który zawiera jedną rzecz, także nudną. Porównując jeden element nudnego typu z innym, nie można nic ciekawego zyskać, ponieważ nie można się niczego nauczyć o elemencie nudnym, poświęcając mu trochę uwagi.

To bardzo różni się od pustego typu [...]. Pusty typ jest bardzo ekscytujący, ponieważ jeśli ktoś kiedykolwiek da ci wartość należącą do niego, wiesz, że już nie żyjesz w Niebie i że wszystko, czego chcesz, jest twoje.

po lewej stronie
źródło
Ciekawy; jeśli definicja ⊥ jest funkcją, której typ zwracany jest ⊥, nigdy nie może się zakończyć, to C ma taki typ. Nazywamy to ulotną pustką.
Joshua
Interesujące, nie wiedziałem tego. Jednak wydaje mi się, że nie jestem zgodny ze standardami .
lewo około