2009-11-10 8 views
6
constante

j'ai créé un petit programme, comme suit:sqrt de math.h provoque une erreur de liaison « undefined reference to sqrt » que lorsque l'argument est pas

#include <math.h> 
    #include <stdio.h> 
    #include <unistd.h> 

    int main(int argc, char *argv[]) { 
    int i; 
    double tmp; 
    double xx; 

    for(i = 1; i <= 30; i++) { 
     xx = (double) i + 0.01; 

     tmp = sqrt(xx); 
     printf("the square root of %0.4f is %0.4f\n", xx,tmp); 
     sleep(1); 
     xx = 0; 
    } 

    return 0; 
} 

Lorsque je tente de compiler ce qui suit commande, j'obtiens une erreur de compilation.

gcc -Wall calc.c -o calc 

retours:

/tmp/ccavWTUB.o: In function `main': 
calc.c:(.text+0x4f): undefined reference to `sqrt' 
collect2: ld returned 1 exit status 

Si je remplace la variable dans l'appel à RACINE (xx) avec une constante comme sqrt (10.2), il compile très bien. Ou, si je lier explicitement comme le suivant:

gcc -Wall -lm calc.c -o calc 

Cela fonctionne également très bien. Quelqu'un peut-il me dire ce qui cause cela? Je suis programmeur C depuis longtemps (et j'ai écrit de petits programmes similaires en utilisant math.h) et je n'ai jamais rien vu de tel.

Ma version de gcc suit:

$ gcc --version 
gcc (Ubuntu 4.3.3-5ubuntu4) 4.3.3 
Copyright (C) 2008 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
$ 
+0

A-t-il toujours besoin de '-lm' si vous spécifiez' --std = c99'? –

+0

Ouais. Bizarre. J'ai aussi essayé d'utiliser -ansi dans le même sens. No-go sans -lm – alesplin

+4

C'est une caractéristique intéressante de gcc que vous devez explicitement lier la bibliothèque de maths - elle attrape tout le monde la première fois. Que le compilateur puisse remplacer silencieusement sqrt (10.2) pour que vous ajoutiez du plaisir! –

Répondre

16

Si vous regardez la sortie du compilateur dans le cas où vous avez utilisé sqrt(10.2), je parie que vous voyez qu'un appel à sqrt() n'est pas en fait .

Cela se produit parce que GCC reconnaît plusieurs fonctions qu'il peut traiter spécialement. Cela lui donne la possibilité de faire certaines optimisations, dans ce cas Constant folding. Ces fonctions spéciales sont appelées Built-ins.

Dans le cas où il doit être lié à la bibliothèque mathématique (parce que vous l'appelez avec une variable), vous devez le lier explicitement. Certains systèmes d'exploitation/compilateurs le font pour vous, c'est pourquoi vous ne l'avez peut-être pas remarqué par le passé.

+2

+1 De nombreux systèmes automatiquement lien contre la bibliothèque de mathématiques pour vous. Certains ne le font pas. Le vôtre ne le fait pas. –

+11

Je pense que ce qu'il essaie de dire c'est que si vous prenez le sqrt d'une constante, le résultat est aussi une constante, donc le compilateur le fait pour vous au moment de la compilation, ne laissant aucun appel à sqrt dans le code. t besoin de lier avec libm (-lm) ​​au moment de la liaison. –

+0

Southern Hospitality a raison. –