pow function working unexpectedly
Giorgos Keramidas
keramida at ceid.upatras.gr
Wed Apr 12 11:05:10 UTC 2006
On 2006-04-11 22:54, Jonathan Herriott <herriojr at gmail.com> wrote:
> I just want to make sure I'm not being stupid before I send in a bug.
> The problem seems to be with gcc when using the pow function in the
> math.h library. Here's code that works:
>
> #include <stdio.h>
> #include <math.h>
>
> int main()
> {
> printf("%f\n", pow(2,3));
> return 0;
> }
>
>
> Now, the following will not compile:
>
> #include <stdio.h>
> #include <math.h>
>
> int main()
> {
> int x = 2; // I tried these as doubles too since the pow function
> takes doubles
> int y = 3;
>
> printf("%f\n", pow(x,y));
> return 0;
> }
>
> I compiled both programs using:
> gcc test.c
>
> The second example gives the following error:
> /var/tmp//ccxtkMwv.o(.text+0x45): In function `main':
> : undefined reference to `pow'
There are two things at work here that are a bit confusing. In the
first case, the arguments of pow() are constants, so the compiler knows
the result of the pow() call at compile-time. GCC tries to optimize
this call away by replacing the entire pow() call with the literal
result. You can see this by:
# $ cat -n pow1.c
# 1 #include <stdio.h>
# 2 #include <math.h>
# 3
# 4 int
# 5 main(void)
# 6 {
# 7
# 8 printf("%f\n", pow(2,3));
# 9 return 0;
# 10 }
If you compile this program to assembler, there is no call to pow():
# $ gcc -std=c99 -pedantic -O2 -S pow1.c
# $ cat -n pow1.s
# 1 .file "pow1.c"
# 2 .section .rodata.str1.1,"aMS", at progbits,1
# 3 .LC1:
# 4 .string "%f\n"
# 5 .text
# 6 .p2align 2,,3
# 7 .globl main
# 8 .type main, @function
# 9 main:
# 10 pushl %ebp
# 11 movl %esp, %ebp
# 12 subl $8, %esp
# 13 andl $-16, %esp
# 14 subl $20, %esp
# 15 pushl $1075838976
# 16 pushl $0
# 17 pushl $.LC1
# 18 call printf
# 19 xorl %eax, %eax
# 20 leave
# 21 ret
# 22 .size main, .-main
# 23 .ident "GCC: (GNU) 3.4.4 [FreeBSD] 20050518"
# $
Lines 15-17 are pushing the arguments of printf() on the stack, so
obviously GCC has pre-calculated the value of pow(2,3) for us.
With the second program, which uses variables for storing the values
passed to pow(), GCC cannot use the same trick, as the *values* of the
variables are only known at runtime. This way, this program:
# $ cat -n pow2.c
# 1 #include <stdio.h>
# 2 #include <math.h>
# 3
# 4 int
# 5 main(void)
# 6 {
# 7 int x = 2; /* I tried these as doubles too since the pow function takes doubles */
# 8 int y = 3;
# 9
# 10 printf("%f\n", pow(x,y));
# 11 return 0;
# 12 }
# $
Compiles to slightly different object code:
# $ gcc -std=c99 -pedantic -O2 -S pow2.c
# $ cat -n pow2.s
# 1 .file "pow2.c"
# 2 .section .rodata.str1.1,"aMS", at progbits,1
# 3 .LC0:
# 4 .string "%f\n"
# 5 .text
# 6 .p2align 2,,3
# 7 .globl main
# 8 .type main, @function
# 9 main:
# 10 pushl %ebp
# 11 movl %esp, %ebp
# 12 subl $8, %esp
# 13 andl $-16, %esp
# 14 subl $32, %esp
# 15 pushl $1074266112
# 16 pushl $0
# 17 pushl $1073741824
# 18 pushl $0
# 19 call pow
# 20 addl $20, %esp
# 21 fstpl (%esp)
# 22 pushl $.LC0
# 23 call printf
# 24 xorl %eax, %eax
# 25 leave
# 26 ret
# 27 .size main, .-main
# 28 .ident "GCC: (GNU) 3.4.4 [FreeBSD] 20050518"
Here a call to pow() is used, so the second program uncovers the fact
that you need the -lm math library to work with math functions, which is
why GCC complains about an undefined reference to pow().
> If I comile with g++, I have no issues. Are these results that I
> should have? If so, why? If not, I'm going to submit the bug on gcc
> (or the linker, but I'm guessing it's the same group).
This is not a C++ program, so you should use a C compiler for it :)
Regards,
Giorgos
More information about the freebsd-questions
mailing list