pourquoi interdire #include f.c ? élément de réponse
quelques réponses citent le fait qu'il ne faut pas inclure des fichiers.c dans un fichier.c sans en donner l'explication et je trouve cela dommage.
je vais tacher d'y répondre.
la compilation d'un fichier.c et je précise bien d"un seul, ce fait en deux étapes: une précompilation suivi de la compilation proprement dit qui aboutit à la création d'un fichier objet en génral un .o
c'est à la précompilation que les includes interviennent.
lorque le précompilateur traite le fichier.c et qu'il rencontre include "toto.h" il ouvre le fichier toto.h et le copie à l'endroit où il se trouve:
exemple
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
/***********************/
fichier.c
/***********************/
int gs32_b;
#include "toto.h"
void main(void)
{
int s32_i
....
i=f(RAD);
...
}
int f( int i_s32_IN)
{
return i_s32_IN*2;
}
/******fin de fichier.c********/
/***********************/
toto.h
/***********************/
#ifndef __JCB_TOTO__
#define __JCB_TOTO__
#define RAD 123456
int f(int);
#endif
/*fin de toto.h*/
A la fin de la precompilation et par consequent en entrée du compilateur nous avons :
int gs32_b;
int f(int);
void main(void)
{
int s32_i
....
i=f(123456);
...
}
int f( int i_s32_IN)
{
return i_s32_IN*2;
}
Remarquons qu'il ny a plus aucun commentaire et que RAD est remplace par sa valeur défini dans toto.h
suposons maintenant que le fonction f nous l'ayons mise dans toto.h
/***********************/
fichier.c
/***********************/
int gs32_b;
#include "toto.h"
void main(void)
{
int s32_i
....
i=f(RAD);
...
}
/******fin de fichier.c********/
/***********************/
toto.h
/***********************/
#ifndef __JCB_TOTO__
#define __JCB_TOTO__
#define RAD 123456
int f( int i_s32_IN)
{
return i_s32_IN*2;
}
#endif
/*fin de toto.h*/
à la fin de la précompilation
nous avons :
int gs32_b;
int f( int i_s32_IN)
{
return i_s32_IN*2;
}
void main(void)
{
int s32_i
....
i=f(123456);
...
} |
La différence est simplement que la fonction f se trouve avant la focnction main ce qui est en soit pas bien génant. Là ou cela ce complique c'est lorsque sue vous avez deux fichier.c qui font appelle tout les deux à toto.h
Au niveau de la compilation pas de probléme les deux fichiers objets seront générés par contre la derniére étape ,l'éditien de lien(link), se passera mal car le linker se trouvera avec deux fonctions f et comme en général les messages des linkers sont trés peu explicites vous aurez peut_etre du mal à l'interpreter et il se peut qu'avec certains outils ( je ne pas dis compilo exprés car nous avons tendance à oublier les différentes étapes nécessaires à la génération d'un éxcécutable). Donc certains outils peuvent ne rien signaler car il vont générer deux fonctions et appeler soit l'une soit l'autre (je ne l'est pas vérifié) l'inconvénient est la place occupée pour rien (sur un pc pas génént pour de l'embarqué ???.
Voilà, j'espére vous avoir éclairé pour cette interdiction absolu d'inclure un fichier.c .
Il ne faut pas oublier que l'inclusion ce fait pour chaque fichier.c d'un projet
par consequent si vous avez N fichier source incluant un fichier.h ,pour chaque fichier .c le precompilateur inclura le fichier.h(et c'est pas grave puisque nécessaire). Le #ifndef __JCB_TOTO__ traditionnel placé en debut des fichiers include est utile uniquement au précompilateur afin qu'il ne travaille pas pour rien en incluant des fichiers déjà inclu notamment,les stdio.h, stdlib.h etc..
Il existe une option pour indiquer au compilateur de s'arréter aprés l'excécution du précompilateur. Je l'utilise dans certains cas lorsquej'ai beaucoup de .h . Si cela vous interesse faites le moi savoir et je vous l'indiquerai (c'est peut être -p)