Pour que le compilateur puisse compiler les fichiers séparément, il faut que vous respectiez les conditions suivantes :
chaque type ou variable utilisé doit être déclaré ;
toute fonction non déclarée doit renvoyer un entier (en C seulement, en C++, l'utilisation d'une fonction non déclarée génère une erreur).
Ces conditions ont des répercussions sur la syntaxe des programmes. Elles seront vues dans les paragraphes suivants.
Les types doivent toujours être déclarés, comme d'habitude. Par exemple, il est interdit d'utiliser une structure client sans l'avoir définie avant sa première utilisation.
Les variables qui sont définies dans un autre fichier doivent être déclarées avant leur première utilisation. Pour cela, on les spécifie comme étant des variables externes, avec le mot-clé extern :
extern int i; /* i est un entier qui est déclaré et créé dans un autre fichier. Ici, il est simplement déclaré. */
Inversement, si une variable ne doit pas être accédée par un autre module, il faut déclarer cette variable statique. Ainsi, même si un autre fichier utilise le mot-clé extern, il ne pourra pas y accéder.
Lorsqu'une fonction se trouve définie dans un autre fichier, il est nécessaire de la déclarer. Pour cela, il suffit de donner sa déclaration (le mot-clé extern est également utilisable, mais facultatif) :
int factorielle(int); /* factorielle est une fonction attendant comme paramètre un entier et renvoyant une valeur entière. Elle est définie dans un autre fichier. */
Il faudra bien faire la distinction entre les fichiers compilés séparément et les fichiers inclus par le préprocesseur. Ces derniers ne sont en effet pas séparés : ils sont compilés avec les fichiers dans lesquels ils sont inclus. Il est donc possible d'inclure du code dans les fichiers d'en-tête.
Les programmes modulaires auront donc typiquement la structure suivante :
Fichier a.h #include Fichier b.c (déclaration des types et --------> (Utilisation des fonctions de a.c, des fonctions de a.c) déclarées dans le fichier inclus a.h) -------------- INDÉPENDANCE DES FICHIERS a.c ET b.c ----------------- Fichier a.h #include Fichier a.c --------> (définition des fonctions déclarées dans le fichier d'en-tête a.h) Compilation : a.c donne a.o, b.c donne b.o ; Édition de liens : a.o et b.o donnent le programme exécutable.
Le langage C++ donne la possibilité d'appeler des fonctions et d'utiliser des variables qui proviennent d'un module écrit dans un autre langage. Pour permettre cela, il dispose de directives permettant d'indiquer comment l'édition de liens doit être faite. La syntaxe permettant de réaliser cela utilise le mot-clé extern, avec le nom du langage entre guillemets. Cette directive d'édition de liens doit précéder les déclarations de variables et de données concernées. Si plusieurs variables ou fonctions utilisent la même directive, elles peuvent être regroupées dans un bloc délimité par des accolades, avec la directive d'édition de liens placée juste avant ce bloc. La syntaxe est donc la suivante :
extern "langage" [déclaration | { déclaration [...] }]
Cependant, les seuls langages qu'une implémentation doit obligatoirement supporter sont les langages "C" et "C++". Pour les autres langages, aucune norme n'est définie et les directives d'édition de liens sont dépendantes de l'implémentation.
Exemple 6-4. Déclarations utilisables en C et en C++
#ifdef __cplusplus extern "C" { #endif extern int EntierC; int FonctionC(void); #ifdef __cplusplus } #endif
Dans l'exemple précédent, la compilation conditionnelle est utilisée pour n'utiliser la directive d'édition de liens que si le code est compilé en C++. Si c'est le cas, la variable EntierC et la fonction FonctionC sont déclarées au compilateur C++ comme étant des objets provenant d'un module C.
Précédent | Sommaire | Suivant |
Syntaxe des outils de compilation | Niveau supérieur | Comment faire du code illisible ? |