Problèmes syntaxiques relatifs à la compilation séparée
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.
Déclaration des types
Les types doivent toujours être définis avant toute utilisation dans un fichier source. Par exemple, il est interdit d’utiliser une structure client sans l’avoir définie avant sa première utilisation. Toutefois, il est possible d’utiliser un pointeur sur un type de donnée sans l’avoir complètement défini. Une simple déclaration du type de base du pointeur suffit en effet dans ce cas là. De même, un simple class MaClasse suffit en C++ pour déclarer une classe sans la définir complètement.
Déclaration des variables
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.
Déclaration des fonctions
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 dans ce cas) :
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. */
Les fonctions inline doivent impérativement être définies dans les fichiers où elles sont utilisées, puisqu’en théorie, elles sont recopiées dans les fonctions qui les utilisent. Cela implique de placer leur définition dans les fichiers d’en-tête .h ou .hpp. Comme le code des fonctions inline est normalement inclus dans le code des fonctions qui les utilisent, les fichiers d’en-tête contenant du code inline peuvent être compilés séparément sans que ces fonctions ne soient définies plusieurs fois. Par conséquent, l’éditeur de liens ne générera pas d’erreur (alors qu’il l’aurait fait si on avait placé le code d’une fonction non inline dans un fichier d’en-tête inclus dans plusieurs fichiers sources .c ou .cpp). Certains programmeurs considèrent qu’il n’est pas bon de placer des définitions de fonctions dans des fichiers d’en-tête, il placent donc toutes leurs fonctions inline dans des fichiers portant l’extension .inl. Ces fichiers sont ensuite inclus soit dans les fichiers d’en-tête .h, soit dans les fichiers .c ou .cpp qui utilisent les fonctions inline.