我无法解释 gcc 4.8.4 展示的以下行为。让我们将以下代码片段命名为pow_main.c
.
#include <stdio.h>
#include <math.h>
int main()
{
printf("%lf\n", pow(2, 10));
return 0;
}
我正在使用以下命令行编译程序:
gcc -c -O0 -Wall pow_main.c -o pow_main.o
请注意,我只是在编译 ( -c
) 程序,而不是链接它。此外,所有编译器优化都被禁用 ( -O0
)。如果我查看目标文件中包含的符号,我会发现:
$ nm pow_main.o
0000000000000000 T main
U printf
在我看来,编译器似乎已经pow
从库中静态地解析了对该方法的引用,或者使用一些内联代码math
优化了调用。pow
- 为什么符号
pow
不存在于目标文件中? - 链接器不负责解析外部引用,无论是静态的还是动态的?
- 目标文件中不应该存在未定义的 ( )
U
符号吗?pow
pow_main.o
平台详情如下:
gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)
编辑:似乎我的两个怀疑之一是正确的。gcc 已经预先计算了表达式并将其替换为常量。
00000000004006dd <main>:
4006dd: 55 push %rbp
4006de: 48 89 e5 mov %rsp,%rbp
4006e1: 48 83 ec 10 sub $0x10,%rsp
4006e5: 48 b8 00 00 00 00 00 movabs $0x4090000000000000,%rax
4006ec: 00 90 40
4006ef: 48 89 45 f8 mov %rax,-0x8(%rbp)
4006f3: f2 0f 10 45 f8 movsd -0x8(%rbp),%xmm0
4006f8: bf e4 07 40 00 mov $0x4007e4,%edi
4006fd: b8 01 00 00 00 mov $0x1,%eax
400702: e8 b9 fe ff ff callq 4005c0 <printf@plt>
400707: 48 ba 00 00 00 00 00 movabs $0x4024000000000000,%rdx
40070e: 00 24 40
400711: 48 b8 00 00 00 00 00 movabs $0x4000000000000000,%rax
400718: 00 00 40
40071b: 48 89 55 f8 mov %rdx,-0x8(%rbp)
40071f: f2 0f 10 4d f8 movsd -0x8(%rbp),%xmm1
400724: 48 89 45 f8 mov %rax,-0x8(%rbp)
400728: f2 0f 10 45 f8 movsd -0x8(%rbp),%xmm0
40072d: e8 7e fe ff ff callq 4005b0 <power@plt>
400732: f2 0f 11 45 f8 movsd %xmm0,-0x8(%rbp)
400737: 48 8b 45 f8 mov -0x8(%rbp),%rax
40073b: 48 89 45 f8 mov %rax,-0x8(%rbp)
40073f: f2 0f 10 45 f8 movsd -0x8(%rbp),%xmm0
400744: bf e4 07 40 00 mov $0x4007e4,%edi
400749: b8 01 00 00 00 mov $0x1,%eax
40074e: e8 6d fe ff ff callq 4005c0 <printf@plt>
400753: b8 00 00 00 00 mov $0x0,%eax
400758: c9 leaveq
400759: c3 retq
40075a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
现在的问题是,如何关闭这样的优化,即使在O0
?