2009-11-10 23 views
6

he creado un pequeño programa, de la siguiente manera:raíz cuadrada de math.h provoca error de vinculador "referencia indefinida a sqrt" sólo cuando el argumento no es una constante

#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; 
} 

Cuando intento compilar esto con el siguiente comando, obtengo un error de compilación.

gcc -Wall calc.c -o calc 

devuelve:

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

Si se sustituye la variable en la llamada a sqrt (xx) con una constante como sqrt (10.2), que compila bien. O bien, si me enlace explícitamente como el siguiente:

gcc -Wall -lm calc.c -o calc 

También funciona muy bien. ¿Alguien puede decirme qué está causando esto? He sido programador de C durante mucho tiempo (y he escrito programas pequeños similares usando math.h) y nunca había visto algo como esto.

Mi versión de gcc sigue:

$ 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

¿Todavía necesita '-lm' si especifica' --std = c99'? –

+0

Sí. Extraño. También intenté usar -ansi con el mismo efecto. No-go sin -lm – alesplin

+4

Es una característica interesante de gcc que necesita vincular explícitamente la biblioteca de matemáticas: atrapa a todo el mundo por primera vez. ¡Que el compilador pueda reemplazar silenciosamente a sqrt (10.2) para que solo le agregue diversión! –

Respuesta

16

Si nos fijamos en la salida del compilador en el caso en que utilizó sqrt(10.2), apuesto a que vea que una llamada a sqrt() no se hace realmente .

Esto sucede porque GCC reconoce varias funciones que puede tratar especialmente. Esto le da la capacidad de hacer ciertas optimizaciones, en este caso Constant folding. Tales funciones especiales se llaman Built-ins.

En el caso en que se debe vincular a la biblioteca matemática (porque la está llamando con una variable), debe vincularla explícitamente. Algunos sistemas operativos/compiladores lo hacen por usted, por lo que es posible que no lo haya notado en el pasado.

+2

+1 Muchos sistemas de forma automática enlace contra la biblioteca de matemáticas por ti. Algunos no. La tuya no. –

+11

Creo que lo que está tratando de decir es que si toma el sqrt de una constante, el resultado también es una constante, por lo que el compilador lo hace por usted en tiempo de compilación, sin dejar llamadas al código en el código, así que no lo hace Necesito enlazar con libm (-lm) ​​en tiempo de enlace. –

+0

Southern Hospitality tiene razón. –

Cuestiones relacionadas