Discussion:
Tonteria en C
(demasiado antiguo para responder)
Patxi R.Y.
2003-08-04 22:28:09 UTC
Permalink
Hola, estoy aprendiendo a programar en C (es una espinita que tengo como
programador profesional :-) y bueno, con un ejemplo de un programa que
realiza una potencia pues me da un error el compilador.

Resulta que se haya la potencia multiplicando el exponente por el logaritmo
de la base, y el compilador falla con las funciones log() y exp().

la funcion es:

double power(int base, int exponente)
{
float valexp;
valexp=exponente*log(base);
return(exp(valexp));
}

La salida del compilador es:
gcc pag69.c -o pag69
/tmp/ccGYUq4f.o(.text+0x98): In function `power':
: undefined reference to `log'
/tmp/ccGYUq4f.o(.text+0xb3): In function `power':
: undefined reference to `exp'
collect2: ld returned 1 exit status

Compilation exited abnormally with code 1 at Tue Aug 5 00:19:32

Y la version del gcc es:
[***@localhost c]$ gcc --version
gcc (GCC) 3.2.2 (Mandrake Linux 9.1 3.2.2-3mdk)

Por su puesto, al principio he incluido la libreria math.h
--
Patxi R. Y.
www.patxi.tk
znôrt
2003-08-04 23:25:32 UTC
Permalink
On Tue, 05 Aug 2003 00:28:09 +0200, "Patxi R.Y."
Post by Patxi R.Y.
gcc pag69.c -o pag69
: undefined reference to `log'
: undefined reference to `exp'
collect2: ld returned 1 exit status
Te falta incluir math.h.

saludos
znôrt
Carlos Fuster
2003-08-05 08:19:10 UTC
Permalink
Seguro que has puesto #include <math.h> ?
Veo en tu función un lio de tipos importante, creo que la funcion log solo
se puede apilcar a float o double , no a int. Cambia los tipos y tratalos
como double, no como int.
--
Carlos Fuster Ribera --> ***@inf.upv.es
--> ***@ya.com
Personal Webpage --> http://ttt.inf.upv.es/~carfusri
"Primero te ignoran, luego se ríen de ti, luego te atacan, entonces ya has
ganado." Ghandi
Fernando Arbeiza
2003-08-05 09:22:19 UTC
Permalink
Post by Carlos Fuster
Veo en tu función un lio de tipos importante, creo que la funcion log solo
se puede apilcar a float o double , no a int. Cambia los tipos y tratalos
como double, no como int.
Creo que el que se ha liado un poquito eres tú ;-) En la función no hay
ningún problema con los tipos si se sabe lo que se está haciendo y se
tiene un poco clara la conversión de tipos. Aunque tienes razón que yo
cambiaría el float por un double (para que no haya tantas conversiones).
Es decir:

double power(int base, int exponente) {
double valexp;

valexp = exponente * log(base);
return exp(valexp);
}

El único problema en C en la conversión de int a double se da si el
valor del int supera el rango representable del double, pero no suele
darse.

El problema de esta función [1] puede ser el valor de base, que puede tomar
valores negativos (y cero); y eso a log no le gusta nada, nada.

[1] Aparte de desbordamientos (overflow y underflow), pero dios no
quiera que haya que meterse con eso ;-)

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Carlos Fuster
2003-08-06 20:48:38 UTC
Permalink
Sólo aclarar que lo del "lio de tipos" que he dicho no lo he dicho por
capricho. Es el estándar de ANSI C, y de POSIX. Si no se cumple, pueden
haber problemas al portar a otras arquitecturas. double log(double x)

No es obligatorio, pero es una buena costumbre es programación de Sistemas.
Fernando Arbeiza
2003-08-06 21:59:50 UTC
Permalink
Post by Carlos Fuster
Sólo aclarar que lo del "lio de tipos" que he dicho no lo he dicho por
capricho.
Ni he pretendido insinuarlo, ten en cuenta que el que ha podido liarse
soy yo ;-)
Post by Carlos Fuster
Es el estándar de ANSI C, y de POSIX. Si no se cumple, pueden
haber problemas al portar a otras arquitecturas. double log(double x)
Pues sí, ahora estoy confuso; está claro que ves algo que yo no sé
(mierda, ahora me pica el gusanillo ;-) ¿Qué problema puede haber al
pasar un int a log en lugar de un double [1]?

[1] Aparte del, creo yo, improbable caso de que el int se salga del
rango de double.

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Carlos Fuster
2003-08-07 07:10:46 UTC
Permalink
En estándar POSIX deben tratarse las funciones. En una arquitectura, un int
se puede reresentar de una manera, mientras que en otra arquitectura pueden
representarse de otra (a nivel de máquina), habitualmente no debe haber
problemas, pero puede haberlos.

Simplemente, piensa, aunque se demostrase que en ninguna arquitectura actual
hay ningún problema, nadie nos asegura que no pueda haberlo en una
arquitectura que se invente en el futuro. Para eso están los estándares.

Hace poco creé un entorno parecido a bash, y me daban mucho la lata con el
cumplir el estándar POSIX. Para hacer una chapucilla no es en absoluto
necesario, pero si se está interesado en hacer un programa sumamente
"correcto", y portable, es lo mejor.

Respecto al libro con el que aprender C, que comentais por allá arriba, yo
también tengo el verde ese, pero a decir verdad, nunca ni lo he mirado.
Para mi el mejor sin duda es "El lenguaje de Programación C" de Kernigham y
Ritchie, ese libro es una maravilla (pero vale una pasta, para tener 10
años, vale unas 4000 pelas y pico, aunque creo que vale la pena). El señor
Ritchie fue el inventor de C, y de UNIX, y lo cierto es que su libro es un
manual de referencia excelente.
--
Carlos Fuster Ribera --> ***@inf.upv.es
--> ***@ya.com
Personal Webpage --> http://ttt.inf.upv.es/~carfusri
"Primero te ignoran, luego se ríen de ti, luego te atacan, entonces ya has
ganado."
FR
2003-08-07 13:56:08 UTC
Permalink
Post by Carlos Fuster
En estándar POSIX deben tratarse las funciones. En una arquitectura, un int
se puede reresentar de una manera, mientras que en otra arquitectura pueden
representarse de otra (a nivel de máquina), habitualmente no debe haber
problemas, pero puede haberlos.
Simplemente, piensa, aunque se demostrase que en ninguna arquitectura actual
hay ningún problema, nadie nos asegura que no pueda haberlo en una
arquitectura que se invente en el futuro. Para eso están los estándares.
Hace poco creé un entorno parecido a bash, y me daban mucho la lata con el
cumplir el estándar POSIX. Para hacer una chapucilla no es en absoluto
necesario, pero si se está interesado en hacer un programa sumamente
"correcto", y portable, es lo mejor.
Je je, el microsh en SSO?
Post by Carlos Fuster
Respecto al libro con el que aprender C, que comentais por allá arriba, yo
también tengo el verde ese, pero a decir verdad, nunca ni lo he mirado.
Para mi el mejor sin duda es "El lenguaje de Programación C" de Kernigham y
Ritchie, ese libro es una maravilla (pero vale una pasta, para tener 10
años, vale unas 4000 pelas y pico, aunque creo que vale la pena). El señor
Ritchie fue el inventor de C, y de UNIX, y lo cierto es que su libro es un
manual de referencia excelente.
Yo tengo ese libro: está ANTICUADO. A mi que me importan las "union" a
estas alturas de la vida? A lo mejor es que tengo una edicion de hace
mucho, pero es un libro anticuado, y seguro que los hay mejores y mas
baratos.
Carlos Fuster
2003-08-07 14:33:02 UTC
Permalink
Diste en la diana, el microsh... ;-)

Insisto, el libro me encanta, pero a gustos colores.
Fernando Arbeiza
2003-08-07 15:19:24 UTC
Permalink
Hola:

Lo que te digo, este calor me está dejando bastante espeso ;-) Veamos...
Post by Carlos Fuster
En estándar POSIX deben tratarse las funciones. En una arquitectura, un int
se puede reresentar de una manera, mientras que en otra arquitectura pueden
representarse de otra (a nivel de máquina), habitualmente no debe haber
problemas, pero puede haberlos.
Totalmente de acuerdo, pero en el caso que nos ocupa, no creo que sea
relevante el tamaño que tenga el int.
Post by Carlos Fuster
Simplemente, piensa, aunque se demostrase que en ninguna arquitectura actual
hay ningún problema, nadie nos asegura que no pueda haberlo en una
arquitectura que se invente en el futuro. Para eso están los estándares.
También estoy de acuerdo. Por eso el estándar de C nos dice que en las
arquitecturas pasadas, presentes y futuras (mientras haya que programar
a los ordenadores ;-) un int se convierte en double sin ningún problema
(a no ser que el valor del int no pueda representarse como double).

Lo he estado pensando, y no consigo ver ningún problema de portabilidad
en un código (por ejemplo) como este:

int i = 3;
double x;

x = log(i);
Post by Carlos Fuster
Hace poco creé un entorno parecido a bash, y me daban mucho la lata con el
cumplir el estándar POSIX. Para hacer una chapucilla no es en absoluto
necesario, pero si se está interesado en hacer un programa sumamente
"correcto", y portable, es lo mejor.
Mucho más portable que el POSIX es el ANSI C, que supongo que es lo que
discutimos e intentamos aplicar aquí :-)

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Fernando Arbeiza
2003-08-05 08:52:33 UTC
Permalink
Hola:

On Tue, 05 Aug 2003 00:28:09 +0200, Patxi R.Y.
Post by Patxi R.Y.
gcc pag69.c -o pag69
: undefined reference to `log'
: undefined reference to `exp'
collect2: ld returned 1 exit status
Compilation exited abnormally with code 1 at Tue Aug 5 00:19:32
Recuerda que gcc no sólo realiza el preprocesado y la compilación; sino
que además llama al enlazador. Es en este proceso (el enlazado) en el
que tienes problemas, la compilación ha terminado sin errores.

Lo que sucede es que has utilizado funciones que el enlazador no
encuentra por no haberle indicado la librería necesaria. Yo cambiaría la
orden de compilación por:

gcc pag69.c -ansi -pedantic -W -Wall -o pag69 -lm

Las opciones -ansi -std=C99 -W -Wall aumentan la cantidad de avisos que
te pueden ser útiles en tu aprendizaje. La opción -lm es la que te
faltaba, y la qye hace que el enlazador encuentre los símbolos que le
faltaban.
Post by Patxi R.Y.
Por su puesto, al principio he incluido la libreria math.h
Otra cosa, ten clara la diferencia entre una librería y un fichero de
cabecera. En pocas palabras, los ficheros de cabecera (*.h) contienen
declaraciones y prototipos necesarios para la compilación del código
fuente; y las librerías contienen código ya compilado necesario para el
enlazado del código objeto.

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Patxi R.Y.
2003-08-05 23:45:40 UTC
Permalink
Bueno, no imaginé que un Tonteria en C daba para tanto xD, la verdad es
que estoy teniendo en cuenta toda la información que estais dando, resulta
bastante util.

Estoy aprendiendo con un pequeño librillo que regalaban con la revista Mas
PC hace cuatro o cinco años y los autores, aunque ellos mismos dicen que es
para empezar de 0, presuponen que no sabemos hacer un simple printf pero
sabemos de memoria las librerias que hayque lincar segun los ficheros de
cabecera que incluyas (lo he dicho bien, no Fernando? xD).

Por cierto, en respuesta a Carlos Fuster, quizás tengas razón en lo que
dices (parece más logico que un logaritmo quepa mejor en un float o en
un double que en un int), buscaré mas información, pero de momento la
Tonteria en C funciona bien sin cambiar eso.

Bueno, seguire aporreando al C a ver si dejo de echar de menos a mis amigos
Pascal-Delphi y (no os altereis) visual basic.

Seguiré informando. Gracias a todos.
--
Patxi R. Y.
www.patxi.tk
J
2003-08-06 22:44:50 UTC
Permalink
Post by Patxi R.Y.
Estoy aprendiendo con un pequeño librillo que regalaban con la revista Mas
PC hace cuatro o cinco años ...
¡¡¡Ese libro verde!!!, con ese empecé yo y te puedo asegurar que es lo
mejor que he encontrado para aprender desde 0 (si vieses el estado en el
que está... se lo he dejado a un montón de gente...)
Patxi R.Y.
2003-08-06 23:58:59 UTC
Permalink
Post by J
¡¡¡Ese libro verde!!!, con ese empecé yo y te puedo asegurar que es lo
mejor que he encontrado para aprender desde 0 (si vieses el estado en el
que está... se lo he dejado a un montón de gente...)
Po zi, el librico ese verde de papel de periódico (casi casi vaya) xD.
Si esta muy bien. Ya me lo terminé cuando lo compre lo que pasa es que
no me iba muy fino el gcc en windows y tenia que suponer que los ejer
cicios los hacia bien (los ejemplos que vienen). Ahora gracias a
gnu/linux estoy contento. Son la pareja ideal C - gnu/linux.

Por cierto, para empezar esta bien, pero en algunas cosas se queda un
poco corto, por ejemplo con los punteros. En pascal me costo tiempo
dominar ese tema y eso que son la mitad de dificiles que en C. Espero
encontrar material complementario.

Pero bueno, era gratis, o eso creo recordar xD. Un saludo.
--
Patxi R. Y.
www.patxi.tk
Loading...