Was bedeutet void in C, C ++ und C #?


170

Suchen Sie nach den Grundlagen, woher der Begriff " nichtig " stammt und warum er als nichtig bezeichnet wird. Die Frage soll jemandem helfen, der keine C-Erfahrung hat und plötzlich eine C-basierte Codebasis betrachtet.


2
Diese Frage mischt 3 Sprachen ... diese alte Frage sollte in 3 verschiedene Fragen aufgeteilt werden.
Stargateur

Antworten:


225

Grundsätzlich bedeutet es "nichts" oder "kein Typ"

Es gibt drei grundlegende Möglichkeiten, wie void verwendet wird:

  1. Funktionsargument: int myFunc(void) - Die Funktion benötigt nichts.

  2. Funktionsrückgabewert: void myFunc(int) - Die Funktion gibt nichts zurück

  3. Generischer Datenzeiger: void* data - 'Daten' ist ein Zeiger auf Daten unbekannten Typs und kann nicht dereferenziert werden

Hinweis: Das voidArgument in einer Funktion ist in C ++ optional, entspricht also int myFunc()genau dem int myFunc(void)und wird in C # vollständig weggelassen. Es ist immer für einen Rückgabewert erforderlich.


7
Die Leere in der Argumentliste ist in C ++ optional, siehe stackoverflow.com/questions/416345/…
Daniel Earwicker

1
Ich würde "kein Typ" anstelle von "keine Größe" verwenden
Kjetil Joergensen

@Earwicker und kjetijor, beide gute Punkte, über die ich diskutiert habe, aber mein schlafloser Verstand brauchte Hilfe;) Danke.
Gerald

9
Nicht anderer Meinung, aber eine zusätzliche Verwendung von void ist der Trick "Cast to void", um Warnungen für nicht verwendete Werte zu unterdrücken. Es ist ein bisschen langwierig, da es nicht wirklich mit der Interpretation der Dinge durch den Compiler übereinstimmt, aber Sie können das so interpretieren, dass es bedeutet, dass ich diesen Wert verwende, um nichts zu tun.
Steve Jessop

22
In C ++ ist void in der Argumentliste optional. In C ist dies jedoch NICHT optional: foo () bedeutet, dass eine beliebige Anzahl von Parametern eines beliebigen Typs verwendet wird, während foo (void) bedeutet, dass keine Parameter verwendet werden.
Adam Rosenfield

33

Ich habe es immer als abwesend verstanden . Hier sind vier Fälle in der C-Sprache, die dieser Verwendung von Abwesenheit entsprechen

  • R f(void)- Funktionsparameter fehlen
  • void f(P)- Rückgabewert fehlt
  • void *p- Die Art des Hinweises fehlt
  • (void) p- Wertverwendung fehlt

Andere C-Nachkommen verwenden es für andere Dinge. Die DProgrammiersprache verwendet es für Fälle, in denen ein Initialisierer fehlt

  • T t = void;- Initialisierungswert fehlt

4
Was macht (void)pdas Ich habe nicht ganz verstanden, was Sie mit "Wertverwendung fehlt" gemeint haben.
Yashas

@Yashas Wenn jemand auch über die (void) var;Aussage verwirrt ist , habe ich detaillierte Antworten unter stackoverflow.com/q/21045615 gefunden .
Arnie97

14

Es gibt zwei Möglichkeiten, void zu verwenden:

void foo(void);

oder

void *bar(void*);

Das erste zeigt an, dass kein Argument übergeben wird oder dass kein Argument zurückgegeben wird.

Der zweite teilt dem Compiler mit, dass den Daten kein Typ zugeordnet ist. Dies bedeutet, dass Sie die Daten, auf die verwiesen wird, erst verwenden können, wenn sie in einen bekannten Typ umgewandelt wurden.

Zum Beispiel werden Sie häufig verwendet sehen void*, wenn Sie eine Schnittstelle haben, die eine Funktion aufruft, deren Parameter nicht im Voraus bekannt sind.

Wenn Sie beispielsweise im Linux-Kernel die Arbeit verschieben, richten Sie eine Funktion ein, die zu einem späteren Zeitpunkt ausgeführt werden soll, indem Sie ihr einen Zeiger auf die auszuführende Funktion und einen Zeiger auf die Daten geben, die an die Funktion übergeben werden sollen:

struct _deferred_work {
sruct list_head mylist;
.worker_func = bar;
.data        = somedata;
} deferred_work;

Dann geht ein Kernel-Thread eine Liste der zurückgestellten Arbeiten durch und führt ihn effektiv aus, wenn er an diesen Knoten gelangt:

bar(somedata);

Dann haben Sie in der Bar:

void bar(void* mydata) {
    int *data = mydata;
    /* do something with data */;
}

13

Es bedeutet "kein Wert". Sie voidgeben an, dass eine Funktion keinen Wert zurückgibt oder keine Parameter oder beides hat. Ziemlich konsistent mit den typischen Verwendungen von Wort void im Englischen.


4

Es zeigt das Fehlen eines Rückgabewerts in einer Funktion an.

Einige Sprachen haben zwei Arten von Unterprogrammen: Prozeduren und Funktionen. Prozeduren sind nur eine Folge von Operationen, während eine Funktion eine Folge von Operationen ist, die ein Ergebnis zurückgeben.

In C und seinen Ableitungen ist der Unterschied zwischen den beiden nicht explizit. Alles ist im Grunde eine Funktion. Das voidSchlüsselwort gibt an, dass es sich nicht um eine "tatsächliche" Funktion handelt, da kein Wert zurückgegeben wird.


3

Stellen Sie sich die Leere als die "leere Struktur" vor. Lassen Sie mich erklären.

Jede Funktion verwendet eine Folge von Parametern, wobei jeder Parameter einen Typ hat. Tatsächlich könnten wir die Parameter in eine Struktur packen, wobei die Strukturschlitze den Parametern entsprechen. Dadurch hat jede Funktion genau ein Argument. In ähnlicher Weise erzeugen Funktionen ein Ergebnis, das einen Typ hat. Es könnte ein Boolescher Wert sein, oder es könnte float sein, oder es könnte eine Struktur sein, die eine beliebige Menge anderer typisierter Werte enthält. Wenn wir eine Sprache mit mehreren Rückgabewerten wollen, können wir einfach darauf bestehen, dass sie in eine Struktur gepackt werden. Tatsächlich konnten wir immer darauf bestehen, dass eine Funktion eine Struktur zurückgab. Jetzt nimmt jede Funktion genau ein Argument und erzeugt genau einen Wert.

Was passiert nun, wenn ich eine Funktion benötige, die den Wert "no" erzeugt? Überlegen Sie, was ich bekomme, wenn ich eine Struktur mit 3 Slots bilde: Sie enthält 3 Werte. Wenn ich 2 Slots habe, enthält es zwei Werte. Wenn es einen Steckplatz hat, einen Wert. Und wenn es null Slots hat, enthält es ... ähm, null Werte oder "kein" Wert. Ich kann mir also eine Funktion vorstellen, die void zurückgibt, als eine Struktur, die keine Werte enthält. Sie können sogar entscheiden, dass "void" ist nur ein Synonym für den Typ, der durch die leere Struktur dargestellt wird, und kein Schlüsselwort in der Sprache (möglicherweise ist es nur ein vordefinierter Typ :)

Ebenso kann ich mir eine Funktion, die keine Werte erfordert, als Akzeptanz einer leeren Struktur vorstellen, z. B. "void".

Auf diese Weise kann ich sogar meine Programmiersprache implementieren. Das Übergeben eines ungültigen Werts nimmt null Bytes ein, daher ist das Übergeben von ungültigen Werten nur ein Sonderfall für das Übergeben anderer Werte beliebiger Größe. Dies erleichtert dem Compiler die Behandlung des Ergebnisses oder Arguments "void". Sie möchten wahrscheinlich eine Sprachfunktion, die ein Funktionsergebnis wegwerfen kann. in C, wenn Sie die nicht leere Ergebnisfunktion foo in der folgenden Anweisung aufrufen: foo (...); Der Compiler weiß, dass foo ein Ergebnis erzeugt und ignoriert es einfach. Wenn void ein Wert ist, funktioniert dies perfekt und jetzt sind "Prozeduren" (die nur ein Adjektiv für eine Funktion mit void-Ergebnis sind) nur triviale Sonderfälle allgemeiner Funktionen.

Void * ist ein bisschen lustiger. Ich glaube nicht, dass die C-Designer auf die oben genannte Weise an Leere gedacht haben. Sie haben gerade ein Schlüsselwort erstellt. Dieses Schlüsselwort war verfügbar, wenn jemand einen Punkt auf einen beliebigen Typ benötigte, also void * als Redewendung in C. Es funktioniert tatsächlich ziemlich gut, wenn Sie void als leere Struktur interpretieren. Ein void * -Zeiger ist die Adresse eines Ortes, an dem diese leere Struktur platziert wurde.

Casts von void * bis T * für andere Typen T funktionieren ebenfalls mit dieser Perspektive. Zeiger-Casts sind ein vollständiger Cheat, der auf den meisten gängigen Architekturen funktioniert, um die Tatsache auszunutzen, dass, wenn ein zusammengesetzter Typ T ein Element mit dem Subtyp S hat, das physisch am Anfang von T in seinem Speicherlayout platziert ist, S * in T * und umgewandelt wird Umgekehrt funktioniert die Verwendung derselben physischen Maschinenadresse in der Regel, da die meisten Maschinenzeiger eine einzige Darstellung haben. Das Ersetzen des Typs S durch den Typ void ergibt genau den gleichen Effekt, und somit funktioniert das Casting zu / von void *.

Die Programmiersprache PARLANSE setzt die oben genannten Ideen ziemlich genau um. Wir haben das Design vermasselt und "void" als Rückgabetyp nicht genau beachtet und haben daher Schlüsselwörter für die Prozedur. Es ist meistens nur eine einfache Syntaxänderung, aber es ist eines der Dinge, an die Sie nicht herankommen, wenn Sie einen umfangreichen Arbeitscode in einer Sprache erhalten.



2

Drei Anwendungsfälle für nichtig:

  1. Funktionssignaturen. void foo(int bar)gibt keinen Wert zurück. int bar(void)nimmt keine Parameter an, aber dies wird normalerweise mit einer leeren Argumentliste ausgedrückt : int bar(). Die Verwendung des Schlüsselworts void entspricht hier seiner englischen Bedeutung.

  2. Generischer Zeiger vom Top-Typ void *, der auf nicht angegebene Daten verweist und nicht dereferenziert werden kann. Hier unterscheidet sich die Bedeutung von void von anderen Bedeutungen von void: universeller Typ vs. kein Typ.

  3. In Abgüssen, (void) new Foo(this)um anzuzeigen, dass der Rückgabewert absichtlich weggeworfen wird. Hier entspricht die Verwendung des Schlüsselworts auch seiner Bedeutung im Englischen.

Die Fälle 1 und 2 wurden bereits von @Gerald behandelt, Fall 3 wurde jedoch noch nicht behandelt.


2

Wenn Sie einem Anfänger das Konzept erklären, kann es hilfreich sein, eine Analogie zu verwenden. Die Verwendung von void in all diesen Fällen hat eine analoge Bedeutung wie eine Seite in einem Buch mit den folgenden Worten: "Diese Seite wurde absichtlich leer gelassen." Es ist für den Compiler eine Unterscheidung zwischen etwas, das als Fehler gekennzeichnet werden soll, und einem Typ, der absichtlich leer gelassen werden soll, da dies das gewünschte Verhalten ist.

Es wird immer in Code angezeigt, in dem normalerweise ein Typ angezeigt wird, z. B. ein Rückgabetyp oder ein Zeigertyp. Aus diesem Grund werden in C # void-Zuordnungen einem tatsächlichen CLR-Typ, System.Void, zugeordnet, da es sich um einen Typ für sich handelt.

Einige Programmiersprachen haben das Konzept der Leere nie entwickelt, so wie einige menschliche Kulturen das Konzept der Zahl Null nie erfunden haben. Void repräsentiert den gleichen Fortschritt in einer Programmiersprache wie das Konzept von Zero für die menschliche Sprache.


Nur eine Anmerkung zu Ihrem letzten Satz - denken Sie daran, dass dies nur für statisch typisierte Sprachen gilt. Dynamisch typisierte Sprachen benötigen keine Leere, da ihre Methoden möglicherweise einfach nichts zurückgeben - die "Leere" wird durch das Fehlen einer Rückgabe impliziert.
Mark Embling

Korrektur meines letzten Kommentars - Ich wollte den letzten Absatz (nicht den Satz) sagen.
Mark Embling

1

Es bedeutet "kein Wert". Sie verwenden void, um anzuzeigen, dass eine Funktion keinen Wert zurückgibt oder keine Parameter oder beides hat. Dies stimmt weitgehend mit den typischen Verwendungen des Wortes void in Englisch überein.

Void sollte nicht mit null verwechselt werden. Null bedeutet, dass für die Variable, deren Adresse sich auf dem Stapel befindet, der Wert auf dem Heap für diese Adresse leer ist.


0

Void wird nur in Methodensignaturen verwendet. Für Rückgabetypen bedeutet dies, dass die Methode nichts an den aufrufenden Code zurückgibt. Für Parameter bedeutet dies, dass keine Parameter an die Methode übergeben werden

z.B

void MethodThatReturnsAndTakesVoid(void)
{
// Method body
}

In C # können wir die Leere für Parameter weglassen und den obigen Code wie folgt schreiben:

void MethodThatReturnsAndTakesVoid()
{
// Method body
}

Void sollte nicht mit null verwechselt werden. Null bedeutet, dass für die Variable, deren Adresse sich auf dem Stapel befindet, der Wert auf dem Heap für diese Adresse leer ist.


0

Void ist ein unvollständiger Typ, der per Definition kein Wert sein kann. Das heißt, es kann kein Wert zugewiesen werden.

Es kann also auch keinen Wert enthalten.



-1

Void bedeutet, dass für den Rückgabetyp von einer Funktion in allen drei Sprachen kein Wert erforderlich ist.


-1

Void ist das Äquivalent zu Visual Basic's Sub.


Nur als Rückgabetyp. Ich kann mir drei weitere Verwendungen von void vorstellen: void-Argumente (Funktion benötigt nichts), void-Zeiger (kein Zeigertyp angegeben) und void-Casts (Wert verwerfen).
c4757p
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.