如果我包含<stdlib.h>或<stdio.h>在C程序中,我不必在编译时链接这些,但我必须链接到<math.h>,使用-lmgcc,例如:
gcc test.c -o test -lm
Run Code Online (Sandbox Code Playgroud)
这是什么原因?为什么我必须显式链接数学库而不是其他库?
我在llvm clang Apple LLVM 8.0.0版(clang-800.0.42.1)上反汇编代码:
int main() {
float a=0.151234;
float b=0.2;
float c=a+b;
printf("%f", c);
}
Run Code Online (Sandbox Code Playgroud)
我编译时没有-O规范,但我也试过-O0(给出相同)和-O2(实际上计算值并存储它预先计算)
产生的反汇编如下(我删除了不相关的部分)
-> 0x100000f30 <+0>: pushq %rbp
0x100000f31 <+1>: movq %rsp, %rbp
0x100000f34 <+4>: subq $0x10, %rsp
0x100000f38 <+8>: leaq 0x6d(%rip), %rdi
0x100000f3f <+15>: movss 0x5d(%rip), %xmm0
0x100000f47 <+23>: movss 0x59(%rip), %xmm1
0x100000f4f <+31>: movss %xmm1, -0x4(%rbp)
0x100000f54 <+36>: movss %xmm0, -0x8(%rbp)
0x100000f59 <+41>: movss -0x4(%rbp), %xmm0
0x100000f5e <+46>: addss -0x8(%rbp), %xmm0
0x100000f63 <+51>: movss %xmm0, -0xc(%rbp)
...
Run Code Online (Sandbox Code Playgroud)
显然它正在做以下事情:
考虑以下代码:
#include <stdio.h>
void foo() {
printf("Hello world\n");
}
void bar() {
printf("Hello world");
}
Run Code Online (Sandbox Code Playgroud)
这两个函数产生的程序集是:
.LC0:
.string "Hello world"
foo():
mov edi, OFFSET FLAT:.LC0
jmp puts
bar():
mov edi, OFFSET FLAT:.LC0
xor eax, eax
jmp printf
Run Code Online (Sandbox Code Playgroud)
现在我知道puts 和 printf之间的区别,但我发现这很有趣,因为 gcc 能够内省 const char* 并确定是调用 printf 还是 puts。
另一个有趣的事情是bar,编译器将返回寄存器 ( eax)清零,即使它是一个void函数。为什么它在那里而不是在里面foo?
我假设编译器“内省了我的字符串”是否正确,或者对此有另一种解释?
这是我的测试代码:
#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
非常简单,我用它编译了它gcc -o helloworld helloworld.c(我也尝试过-g)。
但是,当我时objdump -tT helloworld,输出是:
helloworld: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 abi-note.c
000000000000039c l O .note.ABI-tag 0000000000000020 __abi_tag
0000000000000000 l df *ABS* 0000000000000000 init.c
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
0000000000001070 l F .text 0000000000000000 deregister_tm_clones
00000000000010a0 l F .text 0000000000000000 register_tm_clones
00000000000010e0 l F .text 0000000000000000 __do_global_dtors_aux
0000000000004030 l O .bss 0000000000000001 completed.0
0000000000003df0 l …Run Code Online (Sandbox Code Playgroud)