Das Verständnis der genauen Bedeutung von "void" - Schlüsselwort in C/C++
Wie bereits erklärt, zum Beispiel, hier, es gibt 3 wesentliche Anwendungen für das void-Schlüsselwort (mehr erfahrener C/C++ - Programmierer können überspringen, um die 4. verwenden):
1) Als Rückgabetyp für die Funktion, die nichts zurückgibt,. Diese
verursacht ein code-Beispiel wie diese:
void foo();
int i = foo();
erzeugen einen compiler-Fehler.
2) Als die einzigen parameter in einer Funktion parameter-Liste. AFAIK, eine leere Funktion parameter-Liste ist genau die gleiche, die für den compiler und daher die folgenden 2 Zeilen sind identisch in der Bedeutung:
(edit: es ist nur wahr in c++. Die Kommentare zeigen den Unterschied in c).
int foo();
int foo(void);
3) void* ist eine spezielle Art von generischen Zeiger- es kann auf alle Variablen, die nicht deklariert mit der const-oder volatile-Schlüsselwort, Konvertierung zu/von jeder Art von Daten-Zeiger und Punkt-für alle nicht-member-Funktionen. Darüber hinaus kann nicht aufgelöst werden. Ich gebe keine Beispiele.
Gibt es auch eine 4. verwenden Sie, dass verstehe ich nicht:
4) In die bedingte Kompilierung es wird Häufig in dem Ausdruck (void)0 wie folgt:
//procedure that actually prints error message
void _assert(char* file, int line, char* test);
#ifdef NDEBUG
#define assert(e) ((void)0)
#else
#define assert(e) \
((e) ? (void)0 : \
__assert(__FILE__, __LINE__, #e))
#endif
Ich versuche zu verstehen, das Verhalten dieses Ausdrucks durch Experimente. Alle folgenden gültig sind (kompilieren gut):
int foo(); //some function declaration
int (*fooPtr)(); //function pointer
void(foo);
void(fooPtr);
void(0);
(void)0;
void('a');
void("blabla");
exampleClass e; //some class named exampleClass with a default ctor
void(e);
static_cast<void>(e);
diese sind aber nicht:
void(0) //no semicolon
int i = void(0);
Kann ich daraus schließen, dass "void" (im Rahmen des 4. verwenden) ist einfach eine Besondere Art, dass jede Art werfen kann (ob es im c-Stil oder cpp-Stil), und es kann nie verwendet werden, als lvalue oder rvalue?
- 2 ist das nur wahr, über C++, in C eine leere Funktion Parameterliste bedeutet die Funktion akzeptiert eine beliebige Anzahl nicht angegebener Argumente.
- Sie können sich auch wieder einen Ausdruck
void
von einer Funktion, deren Rückgabetyp istvoid
. - Sie können tun, dass in C++, aber nicht in C. in C, eine void-Funktion kann nur einer bloßen
return;
. (C99 6.8.6.4p1.) - Sind Sie sicher, dass
void(e);
kompiliert in C++? - Die Antwort auf deine Letzte Frage ist nicht:
void()
schafft ein rvalue vom Typvoid
. - das ist, warum ich hasse Fragen über "die C/C++ - Sprache."
- ich verstehe es nicht
void(e)
==(void)e
==static_cast<void>(e)
. Es ist eine gängige Redewendung zum Ausdruck, dass Sie eine variable absichtlich nicht verwendet.- Ich glaube nicht, dass es sich lohnt, zu versuchen zu verstehen, was
void
selbst bedeutet. Es ist nur ein Schlüsselwort, das bedeutet, verschiedene Dinge in verschiedenen Kontexten. Ähnlich wie die keyword -static
bedeutet wie 8 verschiedene Dinge in C++, und ich glaube nicht, dass Sie finden, eine einzige definition, die vollständig erklärt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
James McNellis wies darauf hin, in ein Kommentar oben, dass
void
können verwendet werden, als rvalue über die expressionvoid()
.Er zitiert aus dem aktuellen C++ - standard:
Dies macht es möglich, code zu schreiben, wie ...
und verwenden
foo<void>()
(wahrscheinlich aus anderen Vorlagen-code könnte ich mir vorstellen).Formal
void
ist nur ein unvollständiger Typ, der kann nie abgeschlossen werden.Cheers & hth.
Als für Ihre 2), in C diese:
sind nicht entspricht.
Die erste ist ein old-style-Deklaration (noch unterstützt in der neuesten C-standard), der sagt
foo
wird eine Feste aber nicht spezifizierte Anzahl und Art von argument(en). Ein Anruf, wiefoo(42)
nicht erforderlich ist, eine diagnostische, aber sein Verhalten ist undefiniert, es sei denn, die definition vonfoo
sagt, dass es einen einzigenint
parameter.Der zweite sagt ausdrücklich, dass
foo
nimmt keine Argumente an, undfoo(42)
erfordert eine diagnostische. Die zweite Erklärung ist ein Prototyp, der erste nicht. Die(void)
syntax wurde Hinzugefügt, weil einige spezielle syntax nötig war, um in der Lage sein, zu erklären, einer parameterlosen Funktion, ohne etwas zu schreiben, dass sieht aus wie ein old-style-Deklaration.In der neuen C-code, sollten Sie immer Prototypen verwenden. Old-style-Deklarationen gehalten werden, in der Sprache, die nur zur Unterstützung von alten code.
C++ fiel old-style-Deklarationen. In C++, der zwei Erklärungen von
foo
sind entspricht; dieint foo(void)
form unterstützt wird nur zur Kompatibilität mit C.Ihrem Fall 4) hat eigentlich nichts direkt zu tun mit der bedingten Kompilierung. Gießen Sie einen Ausdruck, um
void
ist eine Möglichkeit der Evaluierung des Ausdrucks und ausdrücklich verwirft seinen Wert. Es wird oft verwendet, um hemmen Warnungen. Zum Beispiel, wennfoo()
gibt einint
Ergebnis, dannals eigenständige Anweisung auslösen könnte, eine Warnung, die Sie verwerfen das Ergebnis, aber
wahrscheinlich teilt dem compiler mit, dass Sie beabsichtigten, dies zu tun.
void
ist ein unvollständiger Typ, der nicht abgeschlossen werden kann. Das bedeutet, dass ein Ausdruck vom Typvoid
können nur in einem Kontext verwendet werden, die nicht erwarten, dass Sie einen Wert ein. Und du hast Recht, ein Ausdruck vom Typvoid
kann nicht verwendet werden, als lvalue oder rvalue. BEARBEITEN: Außer in dem Fall, Alf beschrieben, und nur in C++.void
zu hemmen Warnungen ist pervers, aber es ist sehr nützlich, wenn Sie möchten, um create - Fehler auf, wenn jemand versucht, verwenden Sie den Wert einer Funktion wie makro, das bestimmt nicht, um einen Wert zurückzugeben.Void ist ein Typ mit keine Werte. Da es keine Werte, Ausdrücke der Form
void
kann nur verwendet werden, für Ihre Nebenwirkungen. Hier einige Korrekturen:#1 ja.
#2 Wie bereits erwähnt, ist korrekt, in C++ aber falsch, in C.
#3
void*
ist eine spezielle Art von generischen Zeiger: Nicht ganz. Es ist nicht tragbar, warf einen Funktionszeiger zuvoid*
und wieder zurück.Können Sie jedoch die Besetzung einer Funktion den Zeiger auf eine andere Funktion Zeiger Typ in C, und wieder zurück, ohne sich Gedanken über Portabilität.
#4 Auch verwendet, um explizit anzugeben, um dem compiler, dass ein Wert nicht benötigt.
Empfehle ich immer drehen nicht verwendeten parameter Warnungen für alle Ihre Projekte, weil Sie oft lassen Sie Sie fangen Sie einfachen Tippfehler.
void
ist immer eine unvollständig geben, das heißt, Sie können nie instanziieren ein Objekt des Typsvoid
.Folglich kann es nicht sein alle Werte dieser Art, weder L noch R.Es kann keine lvalue dieser Art, obwohlvoid()
ist ein (p)rvalue. [Dank an @James!]Für
void*
drei gemeinsame verwendet in den Sinn kommen: 1) es ist groß genug, um halten Sie eine beliebige Objekt-Zeiger. 2) dynamic-cast zu void-Zeiger liefert ein Zeiger auf die abgeleitete Typ. 3) es ist die Art von raw-memory-Zeiger, d.h. der Ergebnistyp vonstd::malloc()
und::operator new()
ist das argument, die Art derstd::free()
und::operator delete()
, und von placement-new. Es sollte nicht verwendet werden, für alles andere ist im strengen C++, obwohl es auch in der letzteren Rolle als Puffer argument fürfread
undfwrite
in der C-Bibliothek.void()
schafft ein rvalue vom Typvoid
(oder in C++11, ein prvalue).T()
, woT
ist ein simple-type-specifier oder typename-Planer für eine nicht-array-komplette Objekt-Typ oder die (möglicherweise cv-qualifiziert) void-Typ, erzeugt ein prvalue des angegebenen Typs, die Wert initialisiert (keine Initialisierung erfolgt für dievoid()
Fall)."