tag - Was bedeutet Leere in C, C++ und C#?




winforms tag property (10)

Denken Sie an Leere als die "leere Struktur". Lassen Sie mich erklären.

Jede Funktion nimmt eine Sequenz von Parametern, wobei jeder Parameter einen Typ hat. Tatsächlich könnten wir die Parameter in eine Struktur verpacken, wobei die Strukturschlitze den Parametern entsprechen. Dies hat zur Folge, dass jede Funktion genau ein Argument hat. Ähnlich 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 haben möchten, besteht es leicht darauf, sie in einer Struktur zu verpacken. Tatsächlich könnten wir immer darauf bestehen, dass eine Funktion eine Struktur zurückgegeben hat. Jetzt nimmt jede Funktion genau ein Argument und erzeugt genau einen Wert.

Was passiert nun, wenn ich eine Funktion brauche, die einen "Nein" -Wert erzeugt? Nun, bedenke, was ich bekomme, wenn ich eine Struktur mit 3 Slots formiere: sie enthält 3 Werte. Wenn ich 2 Steckplätze habe, hält es zwei Werte. Wenn es einen Steckplatz hat, einen Wert. Und wenn es null Slots hat, hat es ... uh, Null-Werte oder "no" -Wert. Also kann ich mir eine Funktion vorstellen, die void als Rückgabe einer Struktur liefert, 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 repräsentiert wird, anstatt ein Schlüsselwort in der Sprache (vielleicht ist es nur ein vordefinierter Typ :)

Ähnlich kann ich mir eine Funktion vorstellen, die keine Werte benötigt, um eine leere Struktur zu akzeptieren, zB "void".

Ich kann meine Programmiersprache sogar so implementieren. Das Übergeben eines ungültigen Werts dauert null Byte. Das Übergeben von ungültigen Werten ist also nur ein Spezialfall der Übergabe anderer Werte beliebiger Größe. Dies erleichtert es dem Compiler, das Ergebnis oder Argument "void" zu behandeln. Sie möchten wahrscheinlich eine Sprachfunktion, die ein Funktionsergebnis wegwerfen kann; in C, wenn Sie die nicht-void-Ergebnisfunktion foo in der folgenden Anweisung aufrufen: foo (...); Der Compiler weiß, dass foo ein Ergebnis erzeugt und es einfach ignoriert. Wenn void ein Wert ist, funktioniert das perfekt und jetzt sind "Prozeduren" (die nur ein Adjektiv für eine Funktion mit void result sind) nur triviale Sonderfälle von allgemeinen Funktionen.

Void * ist ein bisschen lustiger. Ich glaube nicht, dass die C-Designer auf die obige Art und Weise auf eine Leere gekommen sind; Sie haben gerade ein Keyword erstellt. Dieses Schlüsselwort war verfügbar, wenn jemand einen Punkt zu einem willkürlichen Typ brauchte, also void * als das Idiom 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 abgelegt wurde.

Für andere Typen T von void * bis T * zu wirken, kann auch mit dieser Perspektive funktionieren. Pointercasts sind ein vollständiger Cheat, der auf den meisten gängigen Architekturen funktioniert, um die Tatsache auszunutzen, dass, wenn ein Verbindungstyp T ein Element mit Subtyp S physisch am Anfang von T in seinem Speicherlayout hat, dann S * zu T * und Umgekehrt tendiert die Verwendung derselben physischen Maschinenadresse dazu, zu arbeiten, 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 Gießen nach / aus void *.

Die PARLANSE-Programmiersprache implementiert die obigen Ideen ziemlich genau. Wir haben in seinem Design geschummelt, und haben nicht auf "void" als Rückgabetyp geachtet und haben daher langauge Schlüsselwörter für das Verfahren. Es ist meist nur eine einfache Syntaxänderung, aber es ist eines der Dinge, zu denen man nicht kommt, sobald man einen großen Body-Code in einer Sprache hat.

Auf der Suche nach den Grundlagen, woher der Begriff VOID kommt und warum er als void bezeichnet wird. Die Absicht der Frage ist, jemanden zu unterstützen, der keine C-Erfahrung hat und plötzlich auf eine C-basierte Codebasis schaut.


Drei Anwendungsfälle für void:

  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 seiner Bedeutung in Englisch.

  2. Generischer Top-Type-Zeiger void * , der auf nicht spezifizierte Daten zeigt und nicht dereferenziert werden kann. Hier unterscheidet sich die Bedeutung von void von anderen Bedeutungen von void: universal type vs. no type.

  3. In Casts wie (void) new Foo(this) um anzuzeigen, dass der Rückgabewert absichtlich weggeworfen wird. Hier stimmt auch die Verwendung des Schlüsselwortes mit seiner Bedeutung in Englisch überein.

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


Es bedeutet "kein Wert". Sie verwenden void um anzugeben, dass eine Funktion keinen Wert zurückgibt oder dass sie keine Parameter oder beides hat. Ziemlich im Einklang mit typischen Verwendungen von Wort void auf Englisch.


Es gibt zwei Möglichkeiten, um void zu verwenden:

void foo(void);

oder

void *bar(void*);

Der erste gibt an, dass kein Argument übergeben wird oder kein Argument zurückgegeben wird.

Die zweite sagt dem Compiler, dass den Daten kein Typ zugeordnet ist, was bedeutet, dass Sie die Daten, auf die verwiesen wird, nicht verwenden können, bis sie in einen bekannten Typ umgewandelt wurden.

Zum Beispiel wird void* oft verwendet, wenn Sie eine Schnittstelle haben, die eine Funktion aufruft, deren Parameter nicht vorher bekannt sein können.

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

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

Dann geht ein Kernel-Thread über eine Liste von verzögerter Arbeit und wenn er zu diesem Knoten gelangt, führt er effektiv aus:

bar(somedata);

Dann in der Bar haben Sie:

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

Grundsätzlich bedeutet es "nichts" oder "keine Art"

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

  1. Funktionsargument: int myFunc(void) - die Funktion übernimmt nichts.

  2. Rückgabewert der Funktion: void myFunc(int) - die Funktion gibt nichts zurück

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

Anmerkung: Das void in einem Funktionsargument ist in C ++ optional, daher ist int myFunc() genau dasselbe wie int myFunc(void) , und es wird vollständig in C # int myFunc(void) . Es ist immer für einen Rückgabewert erforderlich.


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

  • R f(void) - Funktionsparameter fehlen
  • void f(P) - Rückgabewert fehlt
  • void *p - Art von was darauf hingewiesen wird fehlt
  • (void) p - Die Wertnutzung fehlt

Andere C-Nachkommen verwenden es für andere Dinge. Die Programmiersprache D verwendet sie für Fälle, in denen kein Initialisierer vorhanden ist

  • T t = void; - Initialisierungswert fehlt

Leere bedeutet, dass kein Wert für den Rückgabetyp von einer Funktion in allen drei Sprachen benötigt wird.


Void ist das Äquivalent von Visual Basic Sub.


Void wird nur in Methodensignaturen verwendet. Bei 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 Void für Parameter weglassen und können den obigen Code schreiben als:

void MethodThatReturnsAndTakesVoid()
{
// Method body
}

Leere sollte nicht mit Null verwechselt werden. Null bedeutet für die Variable, deren Adresse auf dem Stack liegt, der Wert auf dem Heap für diese Adresse ist leer.


Wenn Sie einem Anfänger das Konzept erklären, könnte es hilfreich sein, eine Analogie zu verwenden. Die Verwendung von void in all diesen Fällen entspricht sinngemäß einer Seite in einem Buch, die die folgenden Worte enthält: "Diese Seite wurde absichtlich leer gelassen." Es ist eine Unterscheidung zum Compiler zwischen etwas, das als Fehler gekennzeichnet werden sollte, und einem Typ, der absichtlich leer bleiben soll, weil dies das gewünschte Verhalten ist.

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

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





terminology