Explication détaillée et application de void * en langage C

Void est interprété comme un nom en anglais comme "vide; espace; espace"; et en langage C, vide est traduit par "aucun type", et le vide correspondant * est "pointeur non typé". Void semble n'avoir que le rôle de "commentaire" et de restreindre le programme. Bien sûr, le "commentaire" ici n'est pas de fournir des commentaires pour nous, mais de fournir un soi-disant commentaire pour le compilateur.

L'adresse de cet article: http://www.cnblogs.com/archimedes/p/c-void-point.html, veuillez indiquer l'adresse source pour la réimpression.

Le rôle du vide:
1. La limitation du retour de fonction, cette situation est plus courante pour nous.

2. La limitation des paramètres de fonction, cette situation est également relativement courante.

En général, ces deux situations sont courantes:

Lorsque la fonction n'a pas besoin de renvoyer une valeur, elle doit être qualifiée avec void, ce que nous appelons le premier cas. Par exemple: void func (int a, char * b).

Lorsque la fonction n'est pas autorisée à accepter des paramètres, vous devez utiliser la qualification void, ce que nous appelons le deuxième cas. Par exemple: int func (void).

Règles d'utilisation des pointeurs void:
1. Un pointeur void peut pointer vers n'importe quel type de données, c'est-à-dire que tout type de pointeur peut être utilisé pour attribuer une valeur à un pointeur void. Par exemple:

  int *a;

  void *p;

  p=a;

Si vous souhaitez affecter le pointeur void p à des pointeurs d'autres types, vous devez transtyper, dans ce cas: a = (int *) p. Dans l'allocation mémoire, on peut voir l'utilisation de pointeurs void: le pointeur retourné par la fonction d'allocation mémoire malloc est void *. Lorsque l'utilisateur utilise ce pointeur, il doit effectuer une conversion de type forcée, c'est-à-dire indiquer explicitement la mémoire pointée Le type de données stockées dans (int ) malloc (1024) signifie qu'il est obligatoire de stocker les données int dans la mémoire pointée par le pointeur void renvoyé par malloc .

2. Dans la norme ANSI C, certaines opérations arithmétiques sur les pointeurs void tels que p ++ ou p + = 1 ne sont pas autorisées, car puisque void est non typé, nous ne savons pas combien d'octets opérer sur chaque opération arithmétique, comme char. type opère sur sizeof (char) octets, tandis que int doit opérer sur sizeof (int) octets. Dans GNU, cela est autorisé, car par défaut, GNU considère void * comme étant le même que char *. Comme il est certain, bien sûr, certaines opérations arithmétiques peuvent être effectuées, où sizeof (* p) == sizeof (char).

Void n'a quasiment que la fonction de "commenter" et de restreindre le programme, car personne n'a jamais défini de variable void, essayons de définir:

void a;

Lorsque cette ligne d'instruction est compilée, une erreur se produit, invitant "utilisation illégale du type" évitez "". Même si la compilation de void a ne fait pas d'erreur, elle n'a aucune signification pratique.

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

 float *p1;
 int *p2;
 p1 = p2;

// L'instruction p1 = p2 compilera l'erreur,
// invite "'=': impossible de convertir de" int * "en" float * "", doit être changé en:
p1 = (float *) p2;
et void * est différent, tout type de pointeur peut lui être directement assigné, sans contrainte

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

Mais cela ne signifie pas que void * peut également être affecté à des pointeurs d'autres types sans lancer. Parce que "no type" peut contenir "typed", et "typed" ne peut pas contenir "no type".

Soyez prudent avec les types de pointeurs vides:

Selon la norme ANSI (American National Standards Institute), vous ne pouvez pas effectuer d'opérations arithmétiques sur des pointeurs vides, c'est-à-dire que les opérations suivantes sont illégales:

void * pvoid;
pvoid++; //ANSI:错误
pvoid += 1; //ANSI:错误

// La raison pour laquelle la norme ANSI reconnaît cela est parce qu'elle insiste: le pointeur pour les opérations arithmétiques doit être sûr de connaître la taille du type de données vers lequel il pointe.
//Par exemple:

int *pint;
pint++; //ANSI:正确

Le résultat de pint ++ est d'augmenter sizeof (int).
Mais GNU ne le pense pas, il spécifie que l'opération arithmétique de void * est cohérente avec char *. Par conséquent, les déclarations suivantes sont toutes correctes dans le compilateur GNU:

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

Le résultat de l'exécution de pvoid ++ est qu'il a augmenté de 1.
Dans la conception réelle du programme, afin de répondre à la norme ANSI et d'améliorer la portabilité du programme, nous pouvons écrire le code pour réaliser la même fonction comme suit:

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

Il y a quelques différences entre GNU et ANSI. De manière générale, GNU est plus «ouvert» que ANSI et fournit plus de support de syntaxe. Mais lorsque nous concevons dans la vraie vie, nous devons toujours répondre autant que possible aux normes ANSI. Si les paramètres de la fonction peuvent être des pointeurs de n'importe quel type, alors les paramètres doivent être déclarés comme void *

Remarque: Le pointeur void peut être n'importe quel type de données, ce qui peut nous apporter des avantages dans le programme. Lorsque la fonction est de type pointeur, nous pouvons le définir comme un pointeur vide, afin que la fonction puisse accepter n'importe quel type de pointeur. Tel que:

Les prototypes de fonctions des fonctions typiques d'opération de mémoire memcpy et memset sont:

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

De cette manière, tout type de pointeur peut être passé dans memcpy et memset, ce qui reflète également vraiment la signification de la fonction d'opération de mémoire, car l'objet sur lequel il opère n'est qu'un morceau de mémoire, quel que soit le type de mémoire (voir C implémentation du langage Programmation générique). Si le type de paramètre de memcpy et memset n'est pas void *, mais char *, c'est vraiment bizarre! De tels memcpy et memset ne sont évidemment pas une fonction "pure, hors du plaisir de bas niveau"! L'apparition de void est juste pour un besoin abstrait.Si vous comprenez correctement le concept de "classe de base abstraite" en orienté objet, il est facile de comprendre le type de données void. Tout comme nous ne pouvons pas définir une instance pour une classe de base abstraite, nous ne pouvons pas définir une variable void (appelons void un "type de données abstrait").

Réimprimé à partir de: https://www.cnblogs.com/wuyudong/p/c-void-point.html

Je suppose que tu aimes

Origine blog.csdn.net/weixin_42692164/article/details/113616383
conseillé
Classement