Da questa risposta sull'ingegneria del software, void viene trattato in modo speciale a seconda di come viene utilizzato. In Ce C++, voidè usato per indicare un'assenza di un tipo di dati, mentre void *è usato per indicare un puntatore che punta ad alcuni dati / spazi in memoria che non hanno un tipo. void *non può essere dereferenziato da solo e deve essere prima lanciato su un altro tipo. Questo cast non deve essere esplicito in C, ma deve essere esplicito in C++. (Ecco perché non lanciamo il valore di ritorno di malloc, che è void *.)
Se utilizzato con una funzione come parametro, voidindica l'assenza totale di qualsiasi parametro ed è l'unico parametro consentito. Il tentativo di utilizzare void come un tipo variabile o includere altri argomenti provoca un errore del compilatore:
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);
^
Allo stesso modo è impossibile dichiarare una variabile con type 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;
voidcome valore di ritorno per una funzione indica che non verranno restituiti dati. Poiché è impossibile dichiarare una variabile di tipo void, è impossibile catturare il valore di ritorno di una voidfunzione, anche con un puntatore vuoto.
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);
^ ~~~~~~
Il senza nome void *è un caso diverso. Un puntatore vuoto indica un puntatore a una posizione in memoria, ma non indica il tipo di dati in quel puntatore. (Questo è usato per ottenere il polimorfismo in C , come con la funzione qsort () .) Questi puntatori possono essere difficili da usare, tuttavia, poiché è molto facile lanciarli accidentalmente nel tipo sbagliato. Il codice seguente non genera errori del compilatore C, ma comporta un comportamento indefinito:
#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);
}
Il seguente codice, tuttavia, è perfettamente legale; il cast da e verso un puntatore vuoto non cambia mai il valore che contiene.
#include <stdio.h>
int main(void) {
double foo = 47.2;
void *bar = &foo;
double *baz = bar;
fprintf(stdout, "%f\n", *baz);
}
47.200000
Come parametro di funzione, void *indica che il tipo di dati sul puntatore in cui si sta passando non è noto e spetta a te, il programmatore, gestire correttamente tutto ciò che si trova in quella posizione di memoria. Come valore restituito, void *indica che il tipo di dati restituiti non è noto o non è tipizzato e deve essere gestito dal programma.
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 un prototipo di funzione significa "nessun dato" e indica nessun valore di ritorno o nessun parametro, void *in un prototipo di funzione significa "i dati nel puntatore a cui viene fornita questa funzione non hanno un tipo noto" e indica un parametro o un valore di ritorno il cui puntatore deve essere castato su un tipo diverso prima di poter utilizzare i dati sul puntatore.