2010-12-13 12 views
9

Digamos que tengo el siguiente fragmento de código:función pow de C se niega a trabajar con exponente variable de

int i; double value; 
for(i = 0; i < CONSTANT; i++) { 
    value = (double)pow(2, i); 
} 

Tratando de compilar este código, se obtiene una "referencia indefinida a '' prisionero de guerra" de error.

La inclusión o exclusión de math.h no hace ninguna diferencia, ya que al final se incluye de todos modos.

Aumentando 2.0 a un poder codificado funciona bien, pero todo falla si sustituyo el exponente por una expresión que contiene i.

¿Qué estoy haciendo mal? Gracias.

+0

¿Qué compilador estás usando? ¿Hay alguna otra declaración posible de 'pow()'? ¿Podría citar el error exactamente? –

+0

Estoy usando GCC y no hay otra declaración de 'pow'. La pregunta es definitivamente respondida; casi todas las respuestas me ayudaron. Ojalá pudiera aceptar más de uno. :) Gracias a todos. –

+5

Mientras que otros han comentado por qué 'pow' no funcionaba, el hecho de que estés usando' pow' es un gran problema con tu código. ** C tiene un operador para exponentes base 2 ** y se llama '<<'. Elimine este uso inútil de 'pow' y reemplácelo con' 1 << i', y olvídese de 'double'. –

Respuesta

16

Es un comportamiento muy interesante, y un buen ejemplo de aprendizaje.

para resolver su problema, agregue

-lm 

a su línea de comando gcc (siempre que estés utilizando gcc). Esto le dice al compilador que se vincule con la biblioteca matemática.

Lo que parece estar sucediendo, es que si usted está utilizando

pow(2.0, 3); 

el compilador se da cuenta de esta expresión se evalúa como una constante, y lo hace simple sustitución.

Por lo tanto, no se debe llamar a ninguna función de biblioteca.

+0

Esta es la explicación que estaba a punto de publicar. El compilador también puede optimizar 'pow (n, 2)' a 'n * n', o similar. – zwol

+1

En realidad, como un comentario de seguimiento ... compilando ese bucle solo, con optimización máxima (-O3) realmente funciona sin -lm. Esto se debe a que el valor no se utiliza más, y el compilador simplemente desenrolla y optimiza el loop inútil y el inútil pow() de distancia, sin necesidad de llamar a la función pow() de la biblioteca libm. – qdot

3

Tiene que establecer un enlace con -lm para incluir realmente la biblioteca matemática.

Funcionó para un valor codificado porque el compilador optimizó la llamada pow lejos.

0

http://www.cplusplus.com/reference/clibrary/cmath/pow/

En C, sólo la versión de tomar dos parámetros dobles existe con este nombre. Las otras sobrecargas solo están disponibles en C++.

Parece que no se puede pasar un int, así que simplemente haz i un doble y eso debería funcionar.

+0

Las "conversiones aritméticas habituales" convierten un int en un doble si es necesario. Estás ladrando al árbol equivocado. – zwol

+0

Y eso merece una rebaja? Por Dios – acron

+0

Es una respuesta incorrecta, y responde la pregunta incorrecta. Así que sí. – zwol

1

El código para pow es parte de la biblioteca de matemáticas. Necesita vincular en esa biblioteca (además de la biblioteca C que está vinculada por defecto).

Para ello, con gcc, especifique -lm sobre la invocación del compilador

gcc ... -lm 
+3

Advertencia menor: los modificadores '-l' siempre deben colocarse * después de * todos los archivos de objeto en la línea de comando. Resulta que funciona en algunas distribuciones de Linux si no lo hace, pero no es confiable. – zwol

3

debe enlazar contra la biblioteca matemática:

gcc program.c -lm 

La razón es que GCC (y algunos otros compiladores) tienen incorporado un pow() función de las constantes literales. Entonces, si llamas al pow() con 2.0 manualmente, el compilador realmente averiguará cuál es la respuesta y la sustituirá por ti. Con una entrada variable, el compilador debe confiar en la biblioteca matemática, con la que debe establecer un vínculo.

Cuestiones relacionadas