简体   繁体   中英

call to pow libm function seems to be getting resolved without linking with the library

I am compiling the following code :

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

main() {
    int x=2, y=3;
    pow(2,3);
    pow(x,y);
}

If I compile this as "gcc file.c" (ie, I am NOT linking with libm.a), the first call to 'pow' does not generate a linker error. Only the secong call to the 'pow' function generates the expected undefined reference to pow - linker error.

I want to know how is the first call getting resolved

You could disassemble you program in gdb to be sure. This is what happens on my machine (cygwin 32, gcc):

This program:

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

int main() {
    int x = 2, y = 3;
    pow(x, y);
    return 0;
}

Generates this code (Notice the call to pow in there):

(gdb) break main
Breakpoint 1 at 0x4011ae: file test.c, line 6.
(gdb) run
...

Breakpoint 1, main () at test.c:6
6           int x = 2, y = 3;
(gdb) disas
Dump of assembler code for function main:
   0x004011a0 <+0>:     push   %ebp
   0x004011a1 <+1>:     mov    %esp,%ebp
   0x004011a3 <+3>:     and    $0xfffffff0,%esp
   0x004011a6 <+6>:     sub    $0x20,%esp
   0x004011a9 <+9>:     call   0x401250 <__main>
=> 0x004011ae <+14>:    movl   $0x2,0x1c(%esp)
   0x004011b6 <+22>:    movl   $0x3,0x18(%esp)
   0x004011be <+30>:    fildl  0x18(%esp)
   0x004011c2 <+34>:    fildl  0x1c(%esp)
   0x004011c6 <+38>:    fxch   %st(1)
   0x004011c8 <+40>:    fstpl  0x8(%esp)
   0x004011cc <+44>:    fstpl  (%esp)
   0x004011cf <+47>:    call   0x401258 <pow>
   0x004011d4 <+52>:    fstp   %st(0)
   0x004011d6 <+54>:    mov    $0x0,%eax
   0x004011db <+59>:    leave
   0x004011dc <+60>:    ret
End of assembler dump.

But if I only have this one:

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

int main() {
    pow(2, 3);
    return 0;
}

All I get is:

Dump of assembler code for function main:
   0x004011a0 <+0>:     push   %ebp
   0x004011a1 <+1>:     mov    %esp,%ebp
   0x004011a3 <+3>:     and    $0xfffffff0,%esp
   0x004011a6 <+6>:     call   0x401230 <__main> 
=> 0x004011ab <+11>:    mov    $0x0,%eax
   0x004011b0 <+16>:    leave
   0x004011b1 <+17>:    ret

Showing pretty clearly your call to pow was removed probably due to some dead code optimization. You're not using the return value and you're calling it for constant values - I guess the compiler considered safe to just get rid of it.

Now considering I actually use pow-s return value:

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

int main() {
    printf("%lf\n", pow(2,3));
    return 0;
}

I get this:

   0x004011a0 <+0>:     push   %ebp
   0x004011a1 <+1>:     mov    %esp,%ebp
   0x004011a3 <+3>:     and    $0xfffffff0,%esp
   0x004011a6 <+6>:     sub    $0x10,%esp
   0x004011a9 <+9>:     call   0x401240 <__main>
   0x004011ae <+14>:    fldl   0x403068
   0x004011b4 <+20>:    fstpl  0x4(%esp)
   0x004011b8 <+24>:    movl   $0x403060,(%esp)
   0x004011bf <+31>:    call   0x401248 <printf>
=> 0x004011c4 <+36>:    mov    $0x0,%eax
   0x004011c9 <+41>:    leave
   0x004011ca <+42>:    ret

Still no call to pow .

And printing the value on the stack that gets sent to printf :

(gdb) x /1f $esp+4
0x22abf4:       8

You can also take a look at this: https://gcc.gnu.org/gcc-4.3/changes.html#mpfropts .

C预编译器意识到这个表达式是一个常量,并且在不使用math.h的情况下将其解析为常量(不调用pow()函数)。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM