De cette réponse sur le génie logiciel, void
est traité spécialement en fonction de la façon dont il est utilisé. Dans C
et C++
, void
est utilisé pour indiquer l'absence d'un type de données, tandis qu'il void *
est utilisé pour indiquer un pointeur qui pointe vers des données / un espace en mémoire qui n'ont pas de type. void *
ne peut pas être déréférencé seul et doit d'abord être converti en un autre type. Cette distribution n'a pas besoin d'être explicite dans C
, mais doit être explicite dans C++
. (C'est pourquoi nous ne convertissons pas la valeur de retour de malloc, qui l'est void *
.)
Lorsqu'il est utilisé avec une fonction comme paramètre, void
signifie une absence totale de tout paramètre et est le seul paramètre autorisé. Tenter d'utiliser void comme un type de variable ou d'inclure d'autres arguments entraîne une erreur de compilation:
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);
^
Il est également impossible de déclarer une variable de 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;
void
comme valeur de retour pour une fonction indique qu'aucune donnée ne sera retournée. Puisqu'il est impossible de déclarer une variable de type void
, il est impossible d'attraper la valeur de retour d'une void
fonction, même avec un pointeur void.
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);
^ ~~~~~~
L'apatride void *
est un cas différent. Un pointeur vide indique un pointeur vers un emplacement en mémoire, mais n'indique pas le type de données à ce pointeur. (Ceci est utilisé pour atteindre le polymorphisme en C , comme avec la fonction qsort () .) Ces pointeurs peuvent cependant être difficiles à utiliser, car il est très facile de les convertir accidentellement dans le mauvais type. Le code ci-dessous ne générera aucune erreur de compilation C
, mais entraînera un comportement indéfini:
#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);
}
Le code suivant, cependant, est parfaitement légal; la conversion vers et depuis un pointeur vide ne modifie jamais la valeur qu'il contient.
#include <stdio.h>
int main(void) {
double foo = 47.2;
void *bar = &foo;
double *baz = bar;
fprintf(stdout, "%f\n", *baz);
}
47.200000
En tant que paramètre de fonction, void *
indique que le type de données sur le pointeur que vous transmettez n'est pas connu, et c'est à vous, le programmeur, de gérer correctement tout ce qui se trouve à cet emplacement mémoire. En tant que valeur de retour, void *
indique que le type des données renvoyées n'est pas connu ou est sans type et doit être géré par le programme.
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
dans un prototype de fonction signifie "pas de données" et indique aucune valeur de retour ou aucun paramètre, void *
dans un prototype de fonction signifie "les données au pointeur que cette fonction est donnée n'ont pas de type connu" et indiquent un paramètre ou une valeur de retour dont le pointeur doit être converti en un type différent avant que les données du pointeur puissent être utilisées.