En anglais, void en tant que nom est défini comme« vide, espace, écart », et en langage C, void se traduit par« aucun type », correspondant àvoid * est« pointeur sans type »。

void semble ne servir que de « commentaire » et à restreindre le programme. Bien sûr, le « commentaire » ici n’est pas destiné à nous, les humains, mais est un soi-disant commentaire fourni au compilateur.


Le rôle de void

1. Restreindre les valeurs de retour des fonctions ; c’est un cas courant.

2. Restreindre les paramètres des fonctions ; c’est aussi assez courant.

Généralement, ce sont les deux cas que nous rencontrons souvent :

  • Lorsqu’une fonction n’a pas besoin de valeur de retour, void doit être utilisé pour la restreindre. C’est le premier cas que nous avons mentionné. Par exemple : void func(int a, char *b).
  • Lorsqu’une fonction n’est pas autorisée à accepter des paramètres, void doit être utilisé pour la restreindre. C’est le deuxième cas que nous avons mentionné. Par exemple : int func(void).

Règles d’utilisation des pointeurs void

1. Un pointeur void peut pointer vers des données de n'importe quel type, c'est-à-dire que tout type de pointeur peut être affecté à un pointeur void. Par exemple :

int *a;
void *p;
p=a;

Si vous voulez affecter le pointeur void p à un pointeur d'un autre type, vous avez besoin d'un transtypage. Dans ce cas :a=(int *)pDans l'allocation mémoire, nous pouvons voir l'utilisation des pointeurs void : le pointeur renvoyé par la fonction d'allocation mémoire malloc estvoid *type. Lors de l'utilisation de ce pointeur, l'utilisateur doit effectuer un transtypage, c'est-à-dire spécifier explicitement quel type de données est stocké dans la mémoire pointée par le pointeur.(int *)malloc(1024)Cela signifie spécifier explicitement que la mémoire pointée par le pointeur void* renvoyé par malloc stocke des données int une à une.

2. Dans la norme ANSI C, les opérations arithmétiques sur les pointeurs void, telles que p++ ou p+=1, ne sont pas autorisées, car comme void n'a pas de type, nous ne savons pas sur combien d'octets chaque opération arithmétique doit opérer. Par exemple, le type char opère sur sizeof(char) octets, tandis que int doit opérer sur sizeof(int) octets. Dans GNU, cependant, c'est autorisé, car par défaut, GNU considèrevoid *etchar *comme identiques. Comme c'est défini, les opérations arithmétiques peuvent certainement être effectuées. Icisizeof(*p)==sizeof(char)。

void ne sert presque qu'à faire office de « commentaire » et à restreindre le programme, car personne ne définit jamais une variable void. Essayons d'en définir une :

void a;

Cette ligne provoquera une erreur de compilation, avec le message« utilisation illégale du type 'void' »Même sivoid ane produit pas d'erreur à la compilation, cela n'a aucune signification pratique.

Comme nous le savons tous, si les pointeurs p1 et p2 sont du même type, alors nous pouvons faire une affectation directe entre p1 et p2 ; si p1 et p2 pointent vers des types de données différents, nous devons utiliser l'opérateur de transtypage pour convertir le type de pointeur du côté droit de l'opérateur d'affectation au type du pointeur de gauche.

float *p1;
int *p2;
p1 = p2;
//其中p1 = p2语句会编译出错,
//提示“'=' : cannot convert from 'int *' to 'float *'”,必须改为:
p1 = (float *)p2;

etvoid *Mais void* est différent ; tout type de pointeur peut lui être directement affecté sans transtypage.

void *p1;
int *p2;
p1 = p2;

Mais cela ne signifie pas quevoid *il puisse aussi être affecté à des pointeurs d'autres types sans conversion de type. Parce que « pas de type » peut accueillir « typé », mais « typé » ne peut pas accueillir « pas de type ».

Faites attention aux types de pointeurs void :

Selon la norme ANSI (American National Standards Institute), les opérations arithmétiques sur les pointeurs void ne sont pas autorisées ; c'est-à-dire que les opérations suivantes sont toutes illégales :

void * pvoid;
pvoid++; //ANSI:错误
pvoid += 1; //ANSI:错误
//ANSI标准之所以这样认定,是因为它坚持:进行算法操作的指针必须是确定知道其指向数据类型大小的。
//例如:
int *pint;
pint++; //ANSI:正确
Le résultat de pint++ est qu'il augmente de sizeof(int).

Mais GNU ne le voit pas ainsi ; il spécifievoid *que les opérations arithmétiques dechar *sont cohérentes. Par conséquent, les instructions suivantes sont toutes correctes dans les compilateurs GNU :

pvoid++; //GNU:正确
pvoid += 1; //GNU:正确

Le résultat de l'exécution de pvoid++ est qu'il augmente de 1.

En programmation réelle, pour respecter la norme ANSI et améliorer la portabilité du programme, nous pouvons écrire du code qui implémente la même fonctionnalité comme suit :

void * pvoid;
((char *)pvoid)++; //ANSI:错误;GNU:正确
(char *)pvoid += 1; //ANSI:错误;GNU:正确

GNU et ANSI présentent également quelques différences. Globalement, GNU est plus « ouvert » qu'ANSI et prend en charge davantage de syntaxe. Mais dans la conception réelle, nous devrions tout de même essayer de nous conformer autant que possible à la norme ANSI. Si le paramètre d'une fonction peut être un pointeur de n'importe quel type, alors son paramètre doit être déclaré commevoid *。

Remarque :Un pointeur void peut pointer vers des données de n'importe quel type, ce qui peut nous apporter certains avantages dans les programmes. Lorsqu'un paramètre de fonction est de type pointeur, nous pouvons le définir comme un pointeur void, afin que la fonction puisse accepter des pointeurs de n'importe quel type. Par exemple :

Des exemples typiques sont les prototypes des fonctions de manipulation de mémoire memcpy et memset, respectivement :

void * memcpy(void *dest, const void *src, size_t len);
void * memset ( void * buffer, int c, size_t num );

De cette façon, des pointeurs de n'importe quel type peuvent être passés à memcpy et memset. Cela reflète vraiment la signification des fonctions de manipulation de mémoire, car l'objet sur lequel elles opèrent n'est qu'un morceau de mémoire, quel que soit le type de cette mémoire (voir Implémentation en langage C de la programmation générique). Si les types de paramètres de memcpy et memset n'étaient pasvoid *, maischar *, ce serait vraiment étrange ! De tels memcpy et memset ne sont manifestement pas des fonctions « pures et raffinées » ! L'apparition de void ne répond qu'au besoin d'abstraction. Si vous comprenez correctement le concept de « classe de base abstraite » en programmation orientée objet, il est également facile de comprendre le type de données void. Tout comme vous ne pouvez pas définir une instance d'une classe de base abstraite, nous ne pouvons pas non plus définir une variable void (appelons analogiquement void un « type de données abstrait »).

URL d'origine : https://www.cnblogs.com/wuyudong/p/c-void-point.html