Léa-Linux & amis :   LinuxFR   GCU-Squad   GNU
Programmation C sous linux
Envoyé par: makacino

Salut tout le monde

Où estl l'erreur dans ce code ?
#include <stdio.h>
#include <math.h>

int main()
{
float a=7.9;
printf("%f\n",floor(a));
return 0;
}

Il me donne cette message d'erreur (fichier : example.c) :
/tmp/ccQW1Y82.o: In function `main':
example.csad smiley.text+0x32): undefined reference to `floor'
collect2: ld returned 1 exit status

Merci d'avance smiling smiley

Poste le Monday 19 December 2005 14:10:45
Répondre     Citer    
Re: Programmation C sous linux
Envoyé par: diancech

En gros l'erreur vient du fait que floor ne doit pas être trouvé dans les libs que tu inclus c'est une fonction je suppose, de quelle lib provient t-elle ?? Il faut trouver ça et l'inclure avec un #include.

Maintenant si c'est une ofnction qui est inclue dans stdio.h ou math.h, il faut allez voir la fonction pour voir si tu lui passe les bons paramètres, ou alors la fonction est employé dans un contexte où elle ne marche pas.

Mais je pencherais plutôt pour le premier problème. A savoir il ne trouve pas la fonction dans les include.

--------------------------------------------------------------------------------------------------------------------------------------------------
Exige beaucoup de toi-même et attends peu des autres. Ainsi beaucoup d'ennuis te seront épargnés. Confucius

Poste le Monday 19 December 2005 14:29:42
Répondre     Citer    
Re: Programmation C sous linux
Envoyé par: abgech

dianceh te réponds partiellement, mais avec une erreur malheureusement assez répandue.

Lorsque tu utilises #include <machin.h> ou "machin.h" tu ne demande pas au compilateur d'aller chercher une librairie, tu lui demande d'insérer, avant la compilation, un fichier source nommé machin.h en remplacement de la ligne #include ... .
La différence entre " " et <> est assez subtile, mais en première analyse, on peut dire que si tu utilises <...>, le compilateur va rechercher le fichier dans ses répertoires de travail, puis ensuite, éventuellement dans ton espace de travail (répertoire courant par defaut, mais tu peux spécifier d'autres répertoires par paramètre du compilateur). Si tu utilises "..." il va chercher uniquement dans ton espace de travail, mais les choses sont un peu plus compliquée et tu peux jouer très finement avec les paramètres du compilateur.

Mais ceci ne te donne en aucun cas accès à une librairie. Cet accès se fait au moment de l'édition des liens (link-edit), je sais la mauvaise habitude qui est prise d'enseigner la programmation avec des environnements intégrés fait que les gens n'ont pratiquement plus idée de ce qu'est le link-edit. Pour faire simple, c'est une phase qui se fait après la traduction en langage machine et qui consiste à mettre ensemble différents bouts de programme en langage machine relogeable (dont certaines adresses ne sont pas encore fixées, le bout de programme peuvent encore être déplacé en mémoire).

En résumé, une compilation C, d'un programme ttt.c sous Linux se fait avec une série de programmes (gcc n'est qu'un script qui regroupe ces phases):
1) Le pré-processeur
Lit le programme écrit par le programmeur et résoud toute les instructions pré-processeurs (celles commençant par un # en colonne 1), donc, dans ton cas le #include. Il produit un fichier appelé ttt.i qui ne contient que du langage C, débarassé des instructions pré-processeurs. Par paramètre, on peut arrêter la compilation à ce stade, par exemple pour "debugger" des instructions pré-processeur un peu rêtives, comme des macros ou des compilations conditionnels un peu torchées.

2) Le compilateur
Lit le fichier ttt.i (du langage C donc), et le traduit (avec optimisation) en langage assembler. Ce langage assembler est contenu dans le fichier ttt.s. Par paramètre, on peut arrêter la compilation à ce stade, par exemple pour venir modifier le langage assembler générer par le compilateur. Par exemple pour écrire des interfaces avec le matériel, c'est parfois nécessaire (de moins on moins heureusement). Inutile de te dire qu'il faut évidemment bien connaître le langage assemble et la façon dont le compilateur génère les instructions assembler. Le ficher ttt.i est détruit à la fin de cette phase. Par paramètre, tu peux demander à le conserver.

3) L'assembler
Traduit le fichier ttt.s (du langage assembler donc) et le traduit en langage machine binaire (en général sur une base 1 instruction assembler donne 1 instruction machine). Comme dit plus haut, ce langage machine est relogeable. Le fichier produit s'appelle ttt.o. Le ficher ttt.s est détruit à la fin de cette phase. Par paramètre, tu peux demander à le conserver.

4) Le link-édit, va prendre le fichier ttt.o ainsi que d'autres fichiers *.o utilisés par ttt.o plus les librairies statiques utilisées par ttt.o pour en faire un programme qui peut être chargé en mémoire. Pour chaque demande de librairie partagée (ou dynamique), il génére un petit code d'appel qui sera utilisé lors de l'exécution. Il produit un exécutable appelé a.out. Par paramètre, tu peux changer ce nom.

Donc, dans ton cas particulier, tu dois mettre dans ton source la ligne
#include <math.h>
cela aura pour effet de venir insérer dans ton programme les prototypes des fonctions mathématiques.
Puis, tu dois dire au link-edit que tu souhaites utiliser la librairie libm.o. Pour ce faire, en appelant gcc, tu rajoute l'option:
-lm
(gcc va automatiquement rajouter lib !)

Voilà, j'ai essayé d'être concis (ça n'est pas toujours évident) et clair (c'est encore moins évident).


Poste le Monday 19 December 2005 19:01:39
Répondre     Citer    
Re: Programmation C sous linux
Envoyé par: diancech

Citation
abgech
Voilà, j'ai essayé d'être concis (ça n'est pas toujours évident) et clair (c'est encore moins évident).

C'est très clair je te rassure, et merci pour cette explication.

;-)

--------------------------------------------------------------------------------------------------------------------------------------------------
Exige beaucoup de toi-même et attends peu des autres. Ainsi beaucoup d'ennuis te seront épargnés. Confucius

Poste le Monday 19 December 2005 19:38:26
Répondre     Citer    
Re: Programmation C sous linux
Envoyé par: Sve@r

Citation
abgech
dianceh te réponds partiellement, mais avec une
erreur malheureusement assez répandue.

Lorsque tu utilises #include <machin.h> ou
"machin.h" tu ne demande pas au compilateur
d'aller chercher une librairie, tu lui demande
d'insérer, avant la compilation, un fichier source
nommé machin.h en remplacement de la ligne
#include ... .
La différence entre " " et <> est assez
subtile, mais en première analyse, on peut dire
que si tu utilises <...>, le compilateur va
rechercher le fichier dans ses répertoires de
travail, puis ensuite, éventuellement dans ton
espace de travail (répertoire courant par defaut,
mais tu peux spécifier d'autres répertoires par
paramètre du compilateur). Si tu utilises "..." il
va chercher uniquement dans ton espace de travail,
mais les choses sont un peu plus compliquée et tu
peux jouer très finement avec les paramètres du
compilateur.

Mais ceci ne te donne en aucun cas accès à une
librairie. Cet accès se fait au moment de
l'édition des liens (link-edit), je sais la
mauvaise habitude qui est prise d'enseigner la
programmation avec des environnements intégrés
fait que les gens n'ont pratiquement plus idée de
ce qu'est le link-edit. Pour faire simple, c'est
une phase qui se fait après la traduction en
langage machine et qui consiste à mettre ensemble
différents bouts de programme en langage machine
relogeable (dont certaines adresses ne sont pas
encore fixées, le bout de programme peuvent encore
être déplacé en mémoire).

En résumé, une compilation C, d'un programme ttt.c
sous Linux se fait avec une série de programmes
(gcc n'est qu'un script qui regroupe ces phases):
1) Le pré-processeur
Lit le programme écrit par le programmeur et
résoud toute les instructions pré-processeurs
(celles commençant par un # en colonne 1), donc,
dans ton cas le #include. Il produit un fichier
appelé ttt.i qui ne contient que du langage C,
débarassé des instructions pré-processeurs. Par
paramètre, on peut arrêter la compilation à ce
stade, par exemple pour "debugger" des
instructions pré-processeur un peu rêtives, comme
des macros ou des compilations conditionnels un
peu torchées.

2) Le compilateur
Lit le fichier ttt.i (du langage C donc), et le
traduit (avec optimisation) en langage assembler.
Ce langage assembler est contenu dans le fichier
ttt.s. Par paramètre, on peut arrêter la
compilation à ce stade, par exemple pour venir
modifier le langage assembler générer par le
compilateur. Par exemple pour écrire des
interfaces avec le matériel, c'est parfois
nécessaire (de moins on moins heureusement).
Inutile de te dire qu'il faut évidemment bien
connaître le langage assemble et la façon dont le
compilateur génère les instructions assembler. Le
ficher ttt.i est détruit à la fin de cette phase.
Par paramètre, tu peux demander à le conserver.

3) L'assembler
Traduit le fichier ttt.s (du langage assembler
donc) et le traduit en langage machine binaire (en
général sur une base 1 instruction assembler donne
1 instruction machine). Comme dit plus haut, ce
langage machine est relogeable. Le fichier produit
s'appelle ttt.o. Le ficher ttt.s est détruit à la
fin de cette phase. Par paramètre, tu peux
demander à le conserver.

4) Le link-édit, va prendre le fichier ttt.o ainsi
que d'autres fichiers *.o utilisés par ttt.o plus
les librairies statiques utilisées par ttt.o pour
en faire un programme qui peut être chargé en
mémoire. Pour chaque demande de librairie partagée
(ou dynamique), il génére un petit code d'appel
qui sera utilisé lors de l'exécution. Il produit
un exécutable appelé a.out. Par paramètre, tu peux
changer ce nom.

Donc, dans ton cas particulier, tu dois mettre
dans ton source la ligne
#include <math.h>
cela aura pour effet de venir insérer dans ton
programme les prototypes des fonctions
mathématiques.
Puis, tu dois dire au link-edit que tu souhaites
utiliser la librairie libm.o. Pour ce faire, en
appelant gcc, tu rajoute l'option:
-lm
(gcc va automatiquement rajouter lib !)

Voilà, j'ai essayé d'être concis (ça n'est pas
toujours évident) et clair (c'est encore moins
évident).

Excellent exposé. juste pour rajouter un petit détail :
l'option "-lqqchose" n'est qu'un raccourci vers "/usr/lib/libqqchose.a"

Donc, soit tu compiles ton pgm en tapant la commande suivante:
cc pgm.c -lm -o pgm

Soit tu tapes la commande suivante
cc pgm.c /usr/lib/libm.a -o pgm

Les deux commandes sont équivalentes et vont demander, lors de l'édition des liens, d'inclure le code des fonctions situées dans la librairie "/usr/lib/libm.a" y compris le code de la fonction "floor()"

Ce lien [fr.lang.free.fr] explique dans le premier chapitre pourquoi et comment on crée des ".h" et pourquoi et comment on crée des librairies


L'homme qui murmurait à l'oreille des pingouins
[fr.lang.free.fr]

Poste le Tuesday 20 December 2005 23:09:08
Répondre     Citer    
Re: Programmation C sous linux
Envoyé par: miguel2i

Citation
Sve@r
Excellent exposé. juste pour rajouter un petit
détail :
l'option "-lqqchose" n'est qu'un raccourci vers
"/usr/lib/libqqchose.a"

Donc, soit tu compiles ton pgm en tapant la
commande suivante:
cc pgm.c -lm -o pgm

Soit tu tapes la commande suivante
cc pgm.c /usr/lib/libm.a -o pgm
C'est à peu près ca.
Sauf que l'option "-lqqchose" permet de lier le programme avec la librairie qqchose soit :
- dynamiquement si il y a un libqqchose.so (par défault)
C'est le cas du "cc pgm.c -lm -o pgm"
- statiquement si il n'y a pas de libqqchose.so et si il y a un libqqchose.a (qui n'est qu'un groupe de .o)
C'est l'équivalent du "cc pgm.c /usr/lib/libm.a -o pgm"

la commande "ldd pgm" dira que pgm est lié avec la libm dans le premier cas pas le deuxième

en passant des options à cc on peut choisir static ou dynamique
voir page 8 du super document donné par Sve@r

Poste le Wednesday 21 December 2005 17:56:42
Répondre     Citer    
Re: Programmation C sous linux
Envoyé par: Tux iN tHe wOod

Ptetre que je me trompe royalement, au quel cas chui dsl, mais pourquoi pas mettre tout simplement :

printf("%f\n",a);
??

Je ne sais pas ce que c'est le floor(a) et d'ailleur je ne l'ai pas vu "floor" dans /usr/include/math.h
S'il a vraiment une utilité, quelle est elle ?

Poste le Saturday 7 January 2006 00:57:00
Répondre     Citer    
Re: Programmation C sous linux
Envoyé par: Sve@r

Citation
Tux iN tHe wOod
Ptetre que je me trompe royalement, au quel cas
chui dsl, mais pourquoi pas mettre tout simplement
:

printf("%f\n",a);
??
Je pense que makacino a un problème avec "floor" et qu'il nous a présenté un exemple réduit au minimum pour nous montrer le problème. Alors que son vrai code doit être un poil plus compliqué que celui présenté ici...


Citation
Tux iN tHe wOod
Je ne sais pas ce que c'est le floor(a) et
d'ailleur je ne l'ai pas vu "floor" dans
/usr/include/math.h
S'il a vraiment une utilité, quelle est elle ?

La fonction "double floor(double x)" renvoie "x" arrondi par défaut (pourquoi un double alors que la valeur décimale est à 0? probablement parce que toutes les fonctions de la libm.a utilisent des doubles en paramètres)

Si t'as d'autres questions de ce style, google et yahoo sont tes amis
[www.google.fr]


L'homme qui murmurait à l'oreille des pingouins
[fr.lang.free.fr]

Poste le Saturday 7 January 2006 01:42:26
Répondre     Citer    

Veuillez vous authentifier auparavant pour commenter.

 

Ce forum !
Programmation C sous linux
Pour poser vos questions sur les scripts shell, le Perl, le C, etc... Attention : nous ne sommes pas des spécialistes du dev, ce forum est juste pour de petites aides ponctuelles concernant le développement et les outils de développement.

Sauf mention contraire, les documentations publiées sont sous licence Creative-Commons