Léa-Linux & amis :   LinuxFR   GCU-Squad   GNU
Débuts difficiles en c...
Envoyé par: lordkrotos

Bonjour tout le monde,

Alors voilà, je débute en c. Je crois que j'ai un problème avec mes fichiers en-tête. Voici le programme:
//"""""""""""""""""""""""""""""""""""""""""//
#include<stdio.h>
#include<math.h>
main()
{
double x;
x=45; /*degré*/
x *=3.1415/180; /*Convertir x en radian*/
printf("\n cos(45)=%f",cos(x));
printf("\n sin(45)=%f",sin(x));
printf("\ntan(45)=%f\n",tan(x));
return 0;
}
//"""""""""""""""""""""""""""""""""""""""""//
Et voici ce que me dit gcc:

[max@localhost chap9]$ gcc -o p137 p137.c
/home/max/tmp/ccnhhlRP.o(.text+0x3b): In function `main':
: undefined reference to `cos'
/home/max/tmp/ccnhhlRP.o(.text+0x63): In function `main':
: undefined reference to `sin'
/home/max/tmp/ccnhhlRP.o(.text+0x8b): In function `main':
: undefined reference to `tan'
collect2: ld returned 1 exit status


Pourtant, j'ai vérifié, et le fichier math.h est dans /usr/include, tout comme stdio.h avec lequel je n'ai jamais eu de pb.
Est-ce que le fichier "math.h" n'est pas "normalisé"?

Merci

Poste le Sunday 11 January 2004 13:53:03
Répondre     Citer    
Re: Débuts difficiles en c...
Envoyé par: lordkrotos

En fait j'ai trouvé la réponse. Il faut lier la bibliothèque "math" pendant la compilation en ajoutant l'option '-lm'. Mais alors: A quoi ça sert de mettre "#include<math.h>" en début de programme???
Merci

Poste le Sunday 11 January 2004 14:24:12
Répondre     Citer    
Re: construction d'un système d'exploitation sous linux
Envoyé par: amina

je veux connaitre le démarche

Poste le Sunday 11 January 2004 17:52:58
Répondre     Citer    
Re: construction d'un système d'exploitation sous linux
Envoyé par: amina

je commance mon travail avec mon copin ,ce ci est la construction d'un système d'exploitation sous linux,nous avons crée le boot secteur,et maintenet nous voulons créer le noyau pou cela je veux un demarche précis
pour continuer mon travail

Poste le Sunday 11 January 2004 18:08:07
Répondre     Citer    
Re: Débuts difficiles en c...
Envoyé par: abgech

>> Mais alors: A quoi ça sert de mettre "#include<math.h>" en début de programme???
La compilation d'un programme écrit en C est un peu moins simple que l'appel à gcc pourrait le laisser penser.
Pour simplifier:
1) Ton programme source (xyz.c) est d'abord lu par un "pré-processeur", celui-ci va exécuter les instructions préprocesseur contenues dans ton programme, toutes celles commençant par # (en principe, par souci de portabilité le # devrait être le premier caractère de la ligne). C'est à cette étape que les fichiers "header" (dans ton cas, math.h, par exemple) sont lus et vont s'insérer à l'emplacement du #include correspondant. Ils s'agit de fichiers sources, essentiellement des déclarations de types, des déclarations de fonctions (prototypes), etc. En aucun cas des instructions exécutables (même si certains malpropres le font ...). À l'aide de #include <math.h> tu vas introduire dans ton sources les prototypes de sin(), cos(), etc, mais absolument pas les instructions correspondantes. Le préprocesseur constitue un fichier xyz.i.
2) Le fichier xyz.i est pris en charge par le compilateur proprement dit. Celui-ci, pour faire simple, va optimiser et traduire le langage C en un programme équivalent en assembler. Le fichier contenant le langage assembler s'appelle xyz.s.
3) Le fichier yxz.s est pris par l'assembler qui le traduit en langage machine relogeable (translatable). Les adresses données dans les instructions sont définies comme si le programme devait être chargé à l'adresse 0 et, surtout, il contient encore des informations qui permettent de déplacer le programme en mémoire. Le fichier porte le nom xyz.o.
4) Le fichier yxz.o constitue l'une des entrées de "l'éditeur de liens", ce programme va alors rechercher dans les librairies statiques (dans ton cas /usr/lib/libm.a) les modules déjà compilés (sin(), cos(), etc) et les incorpore dans ton programme pour en faire un programme exécutable (a.out si tu ne change pas le nom). Avec l'option -lm, tu indiques au link-edit de gcc que tu veux utiliser la librairie statique libm.a.
Voilà, pour l'essentiel et pour faire court. Cela dit, il y a de forte chance qu'en réalité ton programme utilise une librairie partagée (libm.so) (dans le monde window$ on parle de DLL). L'édition de lien est faite alors par le "loader", le programmme qui charge ton programme en mémoire en vue de l'exécution, Pour Linux, un module dynamique n'est chargé qu'au moment de la première utilisation par le programme (pour autant qu'il n'existe pas déjà une copie du module en mémoire. Oublie un peu le dernier paragraphe, et comprends bien les points 1) à 4), tu auras dàjà fait un grand progrès.
Salut, elle est pas belle la vie ?

Poste le Sunday 11 January 2004 20:17:25
Répondre     Citer    
Re: Débuts difficiles en c...
Envoyé par: lordkrotos

Un grand merci pour cette réponse très complète.
a+

Poste le Sunday 11 January 2004 22:59:12
Répondre     Citer    
Re: Débuts difficiles en c...
Envoyé par: svear

Si tu ne linke pas ton pgm à "libm.a" avec "-lm" lors de ta compilation, ton pgm fera appel à des routines sans avoir le code pour les exécuter, d'où ton pb de "undefined reference" comme l'a si bien expliqué "abgech"

Par ailleurs, si tu n'inclues pas "math.h", alors le compilo, lorsqu'il rencontrera pour la première fois l'appel à la fonction "sin()", la considèrera comme une fonction "int" (comportement standard d'un compilo C)
De là, tu auras des résultats aberrants lors de l'appel à "sin" puisque la librairie "libm.a" (que tu auras pris la peine de linker) renverra une valeur en "double" qui sera promptement transformée en "int" par ton pgm mal préparé

C'est pourquoi il faut toujours
1) déclarer les fonctions qu'on va utiliser avant utilisation (c le rôle du ".h"
2) linker la librairie nécessaire au traitement demandé

Poste le Thursday 5 February 2004 21:05:49
Répondre     Citer    
Re: Débuts difficiles en c...
Envoyé par: Mateo

Salut !

Ces réponses sont excellentes !

J'aimerais avoir un tout petit complément d'information s'il vous plaît smiling smiley

Comment gcc sait-il que -lm correspond à libm.a ? Est-ce une convention ? Exemple, j'ai une librairie nommé xyz, si je fais gcc [...] -lxyz, est-ce que cela veut dire qu'il s'agit du fichier libxyz.a ? Ou bien, existe-t-il une "table de liens" qui permet des associations pour rendre la chose plus courte en remplaçant libm.a par m par exemple.

J'espère que je suis clair, ce dont je doute énormément après relecture ;o)

Merci d'avance !

Mateo

Poste le Monday 18 October 2004 00:13:44
Répondre     Citer    
Re: Débuts difficiles en c...
Envoyé par: abgech

On va admettre que c'est clair.
On fait, il s'agit effectivement d'une convention. gcc prend le nom que tu donne en suivant le switch -l, le préfixe par "lib" et le postfixe par ".a" pour obtenir le nom d'une librairie. Reste maintenant à savoir dans quel répertoire aller chercher cette librairie.
S'il s'agit d'une librairie liée à gcc, la règle est simple: dans le/les répertoire(s) "système" (je n'aime pas trop ce mot pour cet usage ...), en principe /usr/lib, mais de toute façon gcc sait où aller rechercher. Pour des librairies que tu constitue toi-même, c'est plus compliqué, de prime abord, et pour simplifier, on peut dire que gcc va d'abord rechercher dans le répertoire courant puis ensuite va explorer les répertoires que tu as donnés avec le switch -L de gcc. En réalité, c'est plus subtil, mais cette explication est suffisante dans la plupart des cas.

Poste le Monday 18 October 2004 07:14:38
Répondre     Citer    
Re: Débuts difficiles en c...
Envoyé par: Mateo

Salut !

Merci beaucoup pour l'info. Il m'est venu une autre petite question :
Que signifie justement l'extension ".a" de la bibliothèque libm.a ?
En comparaison, qu'est-ce que signifient ".so" ?

Il doit y avoir un lien avec la compilation des bibliothèques, j'imagine...

Merci !

Poste le Tuesday 19 October 2004 19:18:32
Répondre     Citer    
Re: Débuts difficiles en c...
Envoyé par: abgech

Le "a" des librairies "lib*.a" signifie, historiquement "archive", elles sont manipulées par un programme qui s'appelle "ar". "ar" ne traite pas uniquement des librairies objet, en fait, il peut mettre en librairie pratiquement n'importe quel type de fichier. Les librairies "lib*.a" sont des librairies statiques, les modules sont incorporés au programme exécutable a la compilation, lors de la phase d'édition des liens (link-edit).

Les librairie "*.so", sont des librairies dynamiques, analogue aux DLL sous Winmachin, mais en plus raffiné. Les modules sont chargés en mémoire au chargement en mémoire du programme lors de son exécution, pour autant qu'une copie de ce module ne soit pas déjà en mémoire. Sous Linux et, plus généralement sous tous les unix et dérivés, il n'y a qu'une seule copie d'un module en mémoire, quel que soit le nombre de processus utilisant ce module, on parle d'un module réentrant. Par exemple, si tu as 10 programmes s'exécutant "simultanément", chacun utilisant sqrt(), il n'y aura qu'une seule copie de sqrt() en mémoire, copie utilisée par chacun des 10 processus. Sous Winmachin, il y a autant de copie du module qu'il y a de programme l'utilisant, dans notre exemple, il y aurait 10 copies de sqrt(), il est vrai que ce n'est pas vraiment important sous windows, 10 programmes simultanés le mettent à genou bien avant.

Poste le Tuesday 19 October 2004 21:23:01
Répondre     Citer    

Veuillez vous authentifier auparavant pour commenter.

 

Ce forum !
Débuts difficiles en c...
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