Forum Clubic

C : Sources .h .c

Bonjour,

pouvez vous m’expliquer la difference entre creer (declaration + code) des fonctions dans un .h, ou les declarer dans un .h et les ecrire dans un .c
Je parle de la difference au niveau du fichier qui va inclure le .h et de la compilation.

Par exmple si je cree des fonctions qui vont souvent me reservir quelle est la meilleure méthode?
merci
Edité le 04/01/2008 à 11:11

Il est d’usage de regrouper les corps des fonctions dans des fichiers .C spécifiques,
et de créer un fichier .H (avec le même nom pour s’y retrouver) qui contient les déclarations de toutes ces fonctions.
Le programme principal n’aura plus qu’à inclure les fichiers .H nécessaires et de préciser,
lors de la compilation,
qu’on veut lier les fichiers contenant les fonctions utilisées au programme principal.

a+

ok.
Et si je veux creer une fonction A dont je veux pouvoir me servir dans plusieurs programme, mais que cette fonction doit apeller une autre fonction B.
Si je met A et B dans util.h et util.c, mes programmes qui incluent util.h auront acces à A et B, mais je ne veux pas qu’ils puissent se servir de B.
Comment faire?

le plus simple est de ne pas appeler la fonction. Si tu inclus un fichier dans lequel tu n’utilises pas toutes les fonctions, ce n’est pas grave (et je pense pas que s’en soit le but, sinon on ne ferait pas de bibliothèques )…

Sinon, si tu veux vraiment “interdire” l’accès à la fonction B, il faut jouer avec les déclarations préprocésseurs dans le .h

#IF DEFINED authorisation_B
//declaration de B

Tu peux très bien faire une fonction dans un *.c qui ne soit pas déclarée dans le *.h.

ok, merci

Et comment faire pour faire comme dans les fonctions “standarts” comme celles dans stdio.h etc…
C’est a dire qu’on inclu le fichier .h et pas besoin de compiler stdio par exemple.

J’ai essayé de creer un fichier util.h et util.c j’ai compilé pour creer util.o
Mais si j’inclu seulement util.h dans test.c et que je compile test.o pour faire l’executable ca ne marche pas il me dis undefined reference to [ma fonction dans util]
(test.c s’est bien compilé en test.o sans probleme)
Edité le 04/01/2008 à 15:55

D’ou la nécessité de faire comme je te l’ai dit.

a+

oui mais je voudrais ne pas avoir a lier les fichiers lors de la compilation, juste a inclure le .h
de la meme maniere qu’on fait un include <stdio.h> : on ne fait pas de lien avec stdio.o …

tout ca car si je crée des fonctions que j’utilise un peu partout je ne veux pas a chaque fois devoir les lier a la main lors de la compilation, j’aimerai que ca soit fait tout seul
Edité le 04/01/2008 à 15:59

Pour le cas de printf and co, c’est juste des fichiers *.o. Ca utilise ce qu’on appelle l’éditeur de liens…

Pour simplifier le compilateur va prendre chaque fichier souce (les *.c) et le compiler pour créer des fichiers objet (binaire). Par la suite, l’éditeur de lien prend tous les fichiers objet de ton programme pour en former un executable. Les headers ne sont donc là que pour donner les prototypes de fonction et les structures en mémoire qui doivent être partagée (des struct?).

Tu peux créer un éxecutable à partir de fichiers objet. L’idée est de compiler tes sources (les *.c) puis de linker tous tes fichiers objet créés AVEC le fichier objet fourni par un autre développeur.

Voici un exemple qui complète ce que dit manu2 (avec une ou deux modifications):
dans util.h:

void fonctionA();

dans util.c:

static void fonctionB()
{
    
}

void fonctionA()
{
    fonctionB();
}

Grâce au mot-clé static en début de fonctionB le compilateur sait qu’il ne doit pas exporter cette fonction (on parle alors de symbole) à l’extérieur pour d’autre code source qui l’utiliserait. fonctionA (qui n’a pas de static) est par contre exportée est peut être utilisée dans un autre code source (il faut juste que ces codes sources donne le prototype de fonctionA dans certains cas*, d’où l’utilité d’un fichier de header ;-)).
J’ai vu sur un site que transformer les fonctions privées en fonctions static permettait d’optimiser la vitesse d’exécution du programme (mais c’est à vérifier).
Pour être complet, en début de fonctionA j’aurait pu ajouté un extern qui indique que l’on exporte ce symbole (mais par défaut toutes les variables/fonctions sont notées comme extern).

En espérant avoir pu être utile (je sais que mes explications partent parfois dans tous les sens)…

*par défaut les fonctions dont aucun prototype n’est donné sont prises comme des fonctions retournant un int (mais c’est pas très propre parce qu’on aime bien savoir d’où vient nos fonctions). D’ailleurs gcc n’aime pas beaucoup quand on utiliser une fonction sans la déclarer (il fait des warnings).
Edité le 05/01/2008 à 00:56

ok, merci pour les explications.
Mais est ce que je peux faire en sorte que le compilateur utilise les .o tout seul, des que j’inclu un .h?
Car je les ai deja cree les .o

Comme quand on inclut des .h des bibliotheques standarts, il va chercher le .o tout seul. Pas besoin de lui dire.
Mais avec un essai que j’ai fait il m’a dis undefined reference lors de la compilation de l’executable.

Et est ce que les .o des bibliotheques standarts sont crees pour tous les compilateurs installes sur la machine?
Si j’ai plusieurs version de gcc ou meme d’autres compilateurs C il y aura un .o pour chaque, que le ocmpilateur ira chercher tout seul?

Source: Wikipédia.

Donc pour résumé il existe plusieurs type de fichier objet. Par contre il ne devrait pas y avoir de différence entre les différentes version d’un compilateur (à mon avis). Sinon pour ton “inclusion” de “.o” je pense que le compilateur ne le fait pas automatiquement.
Comme tu n’ajoutes pas de “.c” dans tes sources il ne génère pas de nouveau “.o” et il ne le link donc pas. Par contre tu peux toujours fait un petit script pour configurer ton linker par ligne de commande.

En ce qui concerne Code::Blocks j’ai pas trouvé la façon de dire au linker d’ajouter un .o dans ses fichiers objet (mais l’option doit sans doute exister).

Ca c’est pas un problème car le but est de générer une seule fois le .o des fonctions “utilitaires”, je peux le faire a la main.
Donc on part du principe que ce .o existe. Ce que je voudrais c’est qu’il le prenne en compte quand j’inclu le .h correspondant.

Peut-être qu’il existe des pargma à utiliser pour faire ça automatiquement (mais ton “.h” sera dépendant d’un compilateur…). Va voir dans la documentation de ton compilateur.