Ab dieser Antwort auf Software Engineering void
wird je nach Verwendungszweck besonders behandelt. In C
und C++
, void
wird verwendet , um anzuzeigen , eine Abwesenheit von einem Datentyp, während die void *
verwendet wird , um anzuzeigen , einen Zeiger, der Punkte auf bestimmte Daten / Platz im Speicher , die nicht einen Typen besitzen. void *
kann nicht alleine dereferenziert werden und muss zuerst in einen anderen Typ umgewandelt werden. Diese Besetzung muss nicht explizit in sein C
, sondern muss explizit in sein C++
. (Aus diesem Grund geben wir den Rückgabewert von malloc nicht aus void *
.)
Bei Verwendung mit einer Funktion als Parameter void
bedeutet dies , dass keine Parameter vorhanden sind, und ist der einzige zulässige Parameter. Der Versuch, void wie einen Variablentyp zu verwenden oder andere Argumente einzuschließen, führt zu einem Compilerfehler:
int foo(void, int); //trying to use "void" as a parameter
int bar(void baz); //trying to use "void" as an argument's type
main.c:1:8: error: 'void' must be the first and only parameter if specified
int foo(void, int);
^
main.c:2:14: error: argument may not have 'void' type
int bar(void baz);
^
Es ist ebenfalls unmöglich, eine Variable mit dem folgenden Typ zu deklarieren void
:
int main(void) {
void qux; //trying to create a variable with type void
}
main.c:5:8: error: variable has incomplete type 'void'
void qux;
void
Ein Rückgabewert für eine Funktion gibt an, dass keine Daten zurückgegeben werden. Da es unmöglich ist, eine Variable vom Typ zu deklarieren void
, ist es unmöglich, den Rückgabewert einer void
Funktion zu erfassen , selbst mit einem ungültigen Zeiger.
void foo(int i) { return; }
int main(void) {
void *j;
j = foo(0);
return 0;
}
main.c:5:5: error: assigning to 'void *' from
incompatible type 'void'
j = foo(0);
^ ~~~~~~
Das Typlose void *
ist ein anderer Fall. Ein ungültiger Zeiger zeigt einen Zeiger auf eine Stelle im Speicher an, zeigt jedoch nicht den Datentyp an diesem Zeiger an. (Dies wird verwendet, um Polymorphismus in C zu erzielen , z. B. mit der Funktion qsort () .) Die Verwendung dieser Zeiger kann jedoch schwierig sein, da es sehr einfach ist, sie versehentlich in den falschen Typ umzuwandeln. Der folgende Code wirft keine Compilerfehler ein C
, führt jedoch zu undefiniertem Verhalten:
#include <stdio.h>
int main(void) {
double foo = 47.2; //create a double
void *bar = &foo; //create a void pointer to that double
char *baz = bar; //create a char pointer from the void pointer, which
//is supposed to hold a double
fprintf(stdout, "%s\n", baz);
}
Der folgende Code ist jedoch vollkommen legal. Das Umwandeln von und zu einem leeren Zeiger ändert niemals den Wert, den er enthält.
#include <stdio.h>
int main(void) {
double foo = 47.2;
void *bar = &foo;
double *baz = bar;
fprintf(stdout, "%f\n", *baz);
}
47.200000
Gibt als Funktionsparameter an, void *
dass der Typ der Daten an dem Zeiger, den Sie übergeben, nicht bekannt ist und es an Ihnen, dem Programmierer, liegt, alles, was sich an diesem Speicherort befindet, richtig zu behandeln. Gibt als Rückgabewert an, void *
dass der Typ der zurückgegebenen Daten nicht bekannt oder typenlos ist und vom Programm verarbeitet werden muss.
int quux(void *); //a function that receives a pointer to data whose type is not known, and returns an int.
void *quuz(int); //a function that receives an int, and returns a pointer to data whose type is not known.
tl; dr void
in einem Funktionsprototyp bedeutet "keine Daten" und zeigt keinen Rückgabewert oder keine Parameter an, void *
in einem Funktionsprototyp bedeutet "die Daten am Zeiger, den diese Funktion erhält, haben keinen bekannten Typ" und gibt einen Parameter oder Rückgabewert an deren Zeiger muss in einen anderen Typ umgewandelt werden, bevor die Daten am Zeiger verwendet werden können.