相关疑难解决方法(0)

为什么必须在C中链接数学库?

如果我包含<stdlib.h><stdio.h>在C程序中,我不必在编译时链接这些,但我必须链接到<math.h>,使用-lmgcc,例如:

gcc test.c -o test -lm
Run Code Online (Sandbox Code Playgroud)

这是什么原因?为什么我必须显式链接数学库而不是其他库?

c compilation math.h

241
推荐指数
7
解决办法
11万
查看次数

为什么clang用-O0生成效率低的asm(对于这个简单的浮点和)?

我在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)

显然它正在做以下事情:

  1. 将两个浮点数加载到寄存器xmm0和xmm1上
  2. 把它们放在堆栈中
  3. 从堆栈加载一个值(不是之前的xmm0)到xmm0
  4. 执行添加. …

c assembly x86-64 compiler-optimization llvm-codegen

4
推荐指数
1
解决办法
333
查看次数

编译器将 printf 更改为 puts

考虑以下代码:

#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

我假设编译器“内省了我的字符串”是否正确,或者对此有另一种解释?

c assembly gcc compiler-optimization

4
推荐指数
2
解决办法
231
查看次数

防止 gcc 将 printf 优化为 put

这是我的测试代码:

#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)

c gcc compilation compiler-optimization

1
推荐指数
1
解决办法
715
查看次数