Pourquoi `typedef void * COMPLEX` est-il utilisé dans cette interface?

J’ai un programme et je ne peux pas comprendre comment cela fonctionne. En voici une partie. Je ne comprends pas la ligne typedef void *COMPLEX , la commande this et la raison pour laquelle la struct COMPLEX_IMPL est utilisée.

 #ifndef _COMPLEX_H #define _COMPLEX_H typedef void *COMPLEX; COMPLEX NewCOMPLEX (double a, double b ); void DeleteCOMPLEX(COMPLEX this ); double GetA (COMPLEX this ); double GetB (COMPLEX this ); COMPLEX AddComplex (COMPLEX c1, COMPLEX c2, COMPLEX res); COMPLEX MultComplex (COMPLEX c1, COMPLEX c2, COMPLEX res); #endif /* _COMPLEX_H */ #ifndef _COMPLEX_H #define _COMPLEX_H typedef void *COMPLEX; COMPLEX NewCOMPLEX (double a, double b ); void DeleteCOMPLEX(COMPLEX this ); double GetA (COMPLEX this ); double GetB (COMPLEX this ); COMPLEX AddComplex (COMPLEX c1, COMPLEX c2, COMPLEX res); COMPLEX MultComplex (COMPLEX c1, COMPLEX c2, COMPLEX res); #endif /* _COMPLEX_H */ 

 #include  #include "complex.h" struct COMPLEX_IMPL { double a; double b; }; double GetA(COMPLEX this) { struct COMPLEX_IMPL *this_impl = (struct COMPLEX_IMPL*)this; return this_impl->a; } 

typedef définit un nom pour un type. Alors

 typedef void *COMPLEX; COMPLEX z; 

est équivalent à

 void *z; 

Un type de pointeur indique normalement le type de données pointé par le pointeur. void * est une exception: c’est un moyen d’avoir un pointeur sans dire quel est le type de la valeur qu’il pointe. Vous pouvez librement affecter n’importe quel type de pointeur à un pointeur void * et inversement.

void * pointeurs void * sont normalement utilisés dans les fonctions de bibliothèque génériques qui doivent fonctionner avec des données de tout type. Par exemple, considérons la fonction de bibliothèque standard memcpy :

 void *memcpy(void *dest, const void *src, size_t n); 

Vous transmettez à cette fonction un pointeur sur un object de n’importe quel type src , un pointeur sur un autre object (qui est généralement, mais pas toujours, du même type) dest et un nombre d’octets à copier. La fonction copie les octets, peu importe la signification des octets, il suffit donc de passer deux pointeurs vers un type non spécifié.

L’utilisation de void * n’est pas une bonne ou une pratique courante en matière de programmation. Un nombre complexe est représenté comme sa partie réelle et sa partie imaginaire:

 struct COMPLEX_IMPL { double a; double b; }; 

Une bibliothèque de nombres complexes typique en ferait le type COMPLEX .

Le code que vous avez posté masque l’implémentation du type COMPLEX . Le fait que les nombres complexes soient mis en œuvre en tant que structure contenant deux membres double n’apparaît que dans complex.c . Les utilisateurs de la bibliothèque voient seulement qu’un COMPLEX est un pointeur sur quelque chose. C’est une forme d’ abstraction de données : masquer les détails de la représentation d’un type de données. Mais c’est mal fait: avec cette définition, tout pointeur sur n’importe quoi peut être assigné à un COMPLEX . La méthode normale consiste à utiliser une structure incomplète , déclarée et visible, mais dont les membres ne sont pas spécifiés. Dans complex.h , vous écririez:

 struct COMPLEX_IMPL; typedef struct COMPLEX_IMPL *COMPLEX; 

Ainsi, la seule façon de créer légalement un COMPLEX_IMPL consiste à COMPLEX_IMPL les fonctions fournies par complex.h , mais une variable de type COMPLEX est visiblement un pointeur sur la représentation d’un nombre complexe défini dans complex.c .

Oh, et this est un nom de variable ordinaire.

 typedef void *COMPLEX; 

fait de COMPLEX un alias pour le type void * . (C’est mal, d’ailleurs, puisque vous ne devriez pas utiliser un type de pointeur et un caractère void désactivera la vérification de type.)

Il n’y a pas de “commande” this , c’est juste le nom d’un argument.

La struct est utilisée pour garder les membres a et b ensemble. C’est à quoi servent les structures.

  • typedef void* COMPLEX fait de ‘COMPLEX’ un alias pour le type de pointeur vide ‘void *’
  • COMPLEX_IMPL est utilisé parce qu’un nombre complexe a deux parties, donc cela les regroupe
  • ‘this’ est une variable

Je pense qu’un tutoriel en C vous serait très utile ici.

typedef void *

utiliser pour définir les fonctions dans les dll utilisées par votre projet