Exood4 Studio - Video Game Development, Toulouse (France)
Exood4 Studios Exood4 Tutorials

   
L a n g a g e   C

L a   g é n é r a t i o n   d e   t y p e s






 Les déclarateurs peuvent être composés pour former des types plus compliqués :

int *tab[10]; /* tableau de 10 pointeurs d'entier */

 Ce type est composé des déclarateurs tableau [] et pointeur *.

 Les déclarateurs de tableaux et de fonctionx sont prioritaires par rapport aux déclarateurs de pointeur, d'où l'utilisation de parenthèses :

int *fct(); /* fonction retournant un pointeur d'entier */
int * (fct());   /* idem, fonction retournant un pointeur d'entier */
int (*fct) ();   /* pointeur sur une fonction retournant un entier */


 int *(*x) [10]; signifie que :
*(*x) [i] est de type int (entier)
(*x) [i] est de type int * (pointeur d'entier)
*x est de type int * [10] (tableau de 10 pointeurs d'entier)
x est de type int () [10] (pointeur de tableau de 10 pointeurs d'entier)
 Le type composé obtenu doit être valide. En particulier :
  • Si le type void est utilisé, cela ne doit être que pour un type void *, une fonction de type void, ou pour la liste de ses paramètres.

  • Les éléments d'un tableau ne peuvent pas être de type fonction : un tableau peut contenir des pointeurs de fonctions mais pas les fonctions elles mêmes.

  • Un tableau ne peut pas être un type de retour d'une fonction : une fonction peut renvoyer un pointeur de tableau ou un pointeur sur le premier élément d'un tableau, mais pas un tableau lui-même.

  • Une fonction ne peut pas retourner de fonction, mais seulement un pointeur de fonction.
 Exemple de compositions valides :

/* p est un pointeur de fonction, retournant un pointeur d'entier */
int *(*p)();

/* T est un tableau de pointeurs de fonctions retournant un entier */
int (*T[])();

/* T est un tableau de pointeurs de fonctions retournant un pointeur d'entier */
int *(*T[])();

/* F est un pointeur de fonction retournant un entier, ce pointeur est */
/* initialisé à l'adresse de la fonction f */
int *(*F)() = f;

/* F est une fonction qui retourne un pointeur de pointeur vers un type long */
long **F();

/* F est une fonction retournant un pointeur de tableau d'éléments de type short */
short (*F())[];

/* F est une fonction qui retourne un pointeur de fonction qui */
/* retourne un pointeur vers un type double */
double *(*F())();

/* F est une fonction qui retourne un pointeur de tableau de */
/* pointeurs de fonctions renvoyant un pointeur de tableaux d'éléments de type char !! */
char (*(*(*F())[])())[];


Typedef


 Les déclarations typedef permettent de nommer des types composés. La syntaxe est la même que pour déclarer un identificateur, le tout précédé du mot clé typedef. L'identificateur devient alors un nom de type, le type étant celui qui aurait été assigné à l'identificateur si la déclaration avait été une déclaration normale :

typedef unsigned char Bool; /* Bool est équivalent au type unsigned char */
typedef char String[255];    /* String est le type chaîne de 255 caractères */
typedef int *Ptr, (Fct)(); /* Ptr est le type pointeur d'entier */
   /* et Fct est le type fonction retournant un entier */
Bool fin, erreur;
Ptr ptr, f(int);
String s, tab[10];
int t = sizeof(String);
Fct fct, *ptrfct;


Les types anonymes


 Il peut parfois être utile de référencer un type sans lui donner de nom. C'est le cas lors de l'écriture d'expressions de conversion de type (opérateur de cast), de calcul de taille de type (opérateur sizeof) ou de l'écriture de prototypes de fonctions. Un déclarateur de type anonyme est un déclarateur de type standard dans lequel a été supprimé l'identificateur :

float * pointeur de réel
char (*)() pointeur d'une fonction retournant un caractère
unsigned *[10] tableau de 10 pointeurs d'entier non signé
int (*(*)())() pointeur d'une fonction retournant un pointeur d'une fonction retournant un entier


Exemple d'utilisation :

double zero (double, double, double (*)(double));

 Cette déclaration pourrait être le prototype d'une fonction calculant le zéro d'une fonction réelle quelconque entre deux bornes réelles. La fonction zero pourrait être appelée comme ceci :

z = zero (1.57, 4.71, sin);

/* calcule le zéro de la fonction sinus dans l'intervalle [1.57;4.71] */


Les conversions explicites


 Un nom de type placé entre parenthèses, suivi d'une expression provoque la conversion dans le type indiqué de la valeur de l'expression. Cette construction s'appelle "cast". Le type peut être anonyme ou être un nom de typedef. Il ne peut être ni une instruction, ni un tableau, ni une fonction. Par exemple, si la taille du type short est 16 bits et celle du type long est 32 bits:

char c;
int i;

c = (char) 0xFFFF:
i = (int) 0xFF;
i = (char) 0xFFFF;

 Ces instructions affectent à chaque fois la valeur 0xFF. Dans les deux premiers cas, les conversions implicites auraient conduit au même résultat. De même :

 (unsigned long) (unsigned short) 0xFFFFFF vaut 0x0000FFFF.



  Retour en haut de page Page suivante