Warum ist der leere Typ von C nicht analog zum leeren / unteren Typ?

28

Wikipedia und andere Quellen, die ich gefunden habe, listen den voidTyp C als Einheitentyp und nicht als leeren Typ auf. Ich finde das verwirrend, da es mir so scheint, als ob es voidbesser zur Definition eines Leer- / Bodentyps passt.

  • voidSoweit ich das beurteilen kann, gibt es keine Werte .
  • Eine Funktion mit dem Rückgabetyp void gibt an, dass die Funktion nichts zurückgibt und daher nur einige Nebenwirkungen verursachen kann.
  • Ein Zeiger vom Typ void*ist ein Subtyp aller anderen Zeigertypen. Konvertierungen von und nach void*in C sind ebenfalls implizit.

Ich bin mir nicht sicher, ob der letzte Punkt als Argument für voideinen leeren Typ von Belang ist, da void*es sich mehr oder weniger um einen Sonderfall handelt, zu dem nicht viel Bezug besteht void.

Andererseits ist er voidselbst kein Untertyp aller anderen Typen, was meines Erachtens eine Voraussetzung dafür ist, dass ein Typ ein unterer Typ ist.

Meta
quelle
10
Mit "gibt nichts zurück" meinen Sie eigentlich "gibt nichts von Interesse zurück", wohingegen eine Funktion mit leerer Ausgabe überhaupt nicht zurückkommt (dh abstürzt oder schleift unendlich).
Turion
2
Als Rückgabetyp ist void ein Einheitentyp.
user253751

Antworten:

38

In C voidwird für mehrere nicht miteinander verbundene Dinge verwendet. Je nachdem, wofür es verwendet wird, kann seine Bedeutung ein Einheitentyp, ein leerer Typ oder etwas anderes sein.

Wenn voides von sich aus verwendet wird (im Gegensatz zu void*einem Zeiger auf void), ist es ein Einheitentyp, dh ein Typ mit einem einzelnen Wert. Von zurückgegebenen Funktionen voidwird gesagt, dass sie „nichts zurückgeben“. Dies bedeutet jedoch, dass sie keine Informationen zurückgeben. Sie geben Informationsbits zurück, was bedeutet, dass sie einen Wert eines Typs zurückgeben, der verschiedene Werte enthält, dh einen Einheitentyp.020=1

Dies ist kein leerer Typ: Eine Funktion, die einen leeren Typ zurückgibt, kann keinen Wert zurückgeben, da es keinen Wert dieses Typs gibt. Eine Funktion, deren Rückgabetyp leer ist, kann nur eine Endlosschleife ausführen, das Programm abbrechen oder eine Ausnahme auslösen ( longjmp) (oder auf andere Weise festlegen, dass keine Rückgabe erfolgt, z. B. durch Übertragung der Steuerung auf einen anderen Thread oder Prozess mit Funktionen, die über Standard C hinausgehen). Um die Dinge nicht zu verwirren, ist es in C üblich, voidanstelle eines leeren Typs einen leeren Typ zu verwenden (C hat keinen leeren Typ).

Der voidTyp erfordert Speicherbits. Da C darauf besteht, dass jedes Objekt eine ganze, von Null verschiedene Anzahl von Speicherbytes belegt, ist es verboten, ein Objekt vom Typ zu erstellen , und es gibt eine spezielle Syntax, um den Wert zurückzugeben (eine Anweisung, bei der der Wert weggelassen wird). Es gibt keine Syntax, die den Wert von type liefert , aber dieser Wert ist immer dann vorhanden, wenn eine Funktion, deren Rückgabetyp "return" ist, zurückgibt.0voidvoidreturnvoidvoid

C hat keinen Bottom-Typ im Sinne eines möglichen Typs. Auch unvollständige Typen geben die allgemeine Natur ihrer Werte an, z. B. Zeiger oder Strukturen oder Vereinigungen oder Funktionen. Ist void*aber ein Zeiger auf einen beliebigen Nicht-Funktionstyp: Es ist das kleinste Element der Algebra von Objektzeigertypen, dh es ist der unterste Objektzeigertyp. Im Gegensatz zum allgemeinen Fall, T*dass Tes sich bei einem Typ um einen nicht leeren Typ handelt, void*handelt es sich nicht um den Typ der Zeiger auf einen Wert vom Typ void, sondern um den Typ der Zeiger auf einen Wert vom nicht angegebenen Typ.

Gilles 'SO - hör auf böse zu sein'
quelle
In C ++ und C89 kann man void zurückgeben. stackoverflow.com/questions/35987493/…
BartekChom
2
Der vierte Absatz ist formal falsch. In C ist die Speichermenge für voidundefiniert und nicht null. Dies ist nicht der Grund, warum Objekte vom Typ voidnicht zulässig sind. Der formale Grund ist, dass voides sich um einen unvollständigen Typ handelt und Objekte keinen unvollständigen Typ haben können.
MSalters
4
@MSalters Nein, was ich geschrieben habe, ist formal korrekt. "Weil" bezieht sich auf die Motivation für die Sprachgestaltung, nicht auf die logischen Schlussfolgerungen innerhalb der Sprachspezifikation. Der voidTyp erfordert 0 Speicherbits. Dies ist der Grund, warum die Designer von C beschlossen haben, voideinen unvollständigen Typ zu erstellen, anstatt zu definieren, dass 0 Byte Speicher (was sich stark auf das Sprachdesign auswirken würde) oder 1 Byte Speicher (was Platz verschwenden würde) benötigt werden. .
Gilles 'SO- hör auf böse zu sein'
1
@ Gilles: Sorry, aber das macht auch keinen Sinn. Falls zulässig, würde der verwendete Speicherplatz 1 Byte pro Objekt vom Typ "void" betragen , und Sie benötigen offensichtlich nicht viele Objekte vom voidTyp " void" . Ganz zu schweigen davon, dass diese Objekte alle anderen Objekte als Alias ​​verwenden könnten, sodass die tatsächliche Verwendung ohnehin null wäre.
MSalters
4
@CodesInChaos: Nun, C ++ erlaubt tatsächlich leere Strukturen, dh struct E { };. Bei Verwendung als Basisklasse kann dies eine Größe von Null haben. (Es gibt wirklich kein C / C ++, die beiden Sprachen treffen ihre eigenen Entscheidungen und können sich in diesen Bereichen unterscheiden. C hat offensichtlich keine leeren Basisklassen, da es überhaupt keine OO hat.)
MSalters
11

Der Name "leerer Typ" ist vielleicht verwirrend. Dies bedeutet, wie Sie selbst sagen, dass der Typ keine Werte enthält . Die Angabe "leer" bezieht sich nicht auf einzelne Werte des Typs, sondern auf den gesamten Typ, der als ~ Menge möglicher Werte betrachtet wird. Das bedeutet also nicht so etwas wie "Eine Funktion, die voidzurückgibt, gibt keine Informationen zurück", sondern "Es gibt keinen Wert vom Typ ".

Dies bedeutet eine Funktion , deren Ergebnistyp kann nie enden. Wenn es beendet würde, müsste ein Wert von zurückgegeben werden , aber nun, ein solcher Wert existiert nicht.

Dies bedeutet auch, dass nicht einmal diskutiert werden kann, wie viele Informationen ein leerer Wert enthalten würde, da es keinen solchen Wert gibt. (Wenn Sie so wollen, ist eine unsinnige Aussage wie „jeder Wert eines leeren Typs enthält genau 35093658 Informationsbits“ vakuumtreu.) Es ist einigermaßen nützlich (wenn auch nicht wirklich korrekt), sich Werte als unendlich viele Informationen enthaltend vorzustellen .

Während eine C-Funktion mit "return type" voideindeutig zurückgeben kann , gibt sie in ihrem Rückgabewert keine Informationen aus. Genau das zeichnet einen Einheitentyp aus: Seine Werte enthalten keine Informationen, da es nur einen solchen Wert gibt (daher können Sie immer sagen, wie hoch der Rückgabewert sein wird, auch ohne sich die Mühe zu machen, die Funktion jemals aufzurufen).

Um Conor McBride (transliteriert nach C) zu zitieren :

voidbedeutet "langweilig". Es bedeutet die langweilige Art, die eine Sache enthält, auch langweilig. Es gibt nichts Interessantes, wenn Sie ein Element des langweiligen Typs mit einem anderen vergleichen, da Sie nichts über ein Element des langweiligen Typs lernen müssen, indem Sie ihm Ihre Aufmerksamkeit schenken.

Es unterscheidet sich sehr vom leeren Typ [...]. Der leere Typ ist sehr aufregend, denn wenn dir jemals jemand einen dazugehörigen Wert gibt, weißt du, dass du bereits tot und im Himmel bist und alles, was du willst, dir gehört.

links herum
quelle
Interessant; wenn die Definition von ⊥ die Funktion ist, deren Rückgabetyp ⊥ ist, kann C niemals enden, dann hat C einen solchen Typ. Wir nennen es volatile void.
Joshua
Interessant, das wusste ich nicht. Eigentlich scheint ich aber nicht standardkonform zu sein .
Abfahrt um 07.09.16