常量VS在数学库变量 [英] literal constant vs variable in math library

查看:138
本文介绍了常量VS在数学库变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我知道,在 C 您需要将code链接到数学库,的libm ,以便能够使用其功能。今天,当我试图证明这一点给朋友,并解释为什么你需要这样做,我碰到以下情况下,我不明白。

So, I know that in C you need to link the code to the math library, libm, to be able to use its functions. Today, while I was trying to demonstrate this to a friend, and explain why you need to do this, I came across the following situation that I do not understand.

考虑以下code:

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

/* #define VARIABLE */

int main(void)
{
#ifdef VARIABLE
    double a = 2.0;
    double b = sqrt(a);
    printf("b = %lf\n",b);
#else
    double b = sqrt(2.0);
    printf("b = %lf\n",b);
#endif
    return 0;
}

如果变量定义,则需要对的libm 链接,你通常会期望;否则,你得到通常的main.c :(文字+ 0x29):未定义引用开方链接表明编译器无法找到该函数的定义错误开方。我很惊讶地看到,如果我评论#定义变量中,code运行良好,其结果是正确的!

If VARIABLE is defined, you need to link against libm as you would normally expect; otherwise you get the usual main.c:(.text+0x29): undefined reference to sqrt linking error indicating that the compiler cannot find the definition for the function sqrt. I was surprised to see that if I comment #define VARIABLE, the code runs fine and the result is correct!

为什么我需要链接到的libm 使用变量的时候,但我并不需要做的,所以当使用文字常量?编译器如何找到的开方时,库不链接的定义是什么?我使用的linux下的 GCC 4.4.5

Why is it that I need to link to libm when variables are used but I don't need to do so when literal constants are used? How does the compiler find the definition of sqrt when the library is not linked? I'm using gcc 4.4.5 under linux.

推荐答案

大家都提到了,是的,它具有的常量折叠

As everyone mentions, yes it has to do with constant folding.

随着优化关闭,GCC似乎只有这样做时,的sqrt(2.0)被使用。这里的证据:

With optimizations off, GCC only seems to do it when sqrt(2.0) is used. Here's the evidence:

案例1:随着变量

    .file   "main.c"
    .section    .rodata
.LC1:
    .string "b = %lf\n"
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    fldl    .LC0
    fstpl   24(%esp)
    fldl    24(%esp)
    fsqrt
    fucom   %st(0)
    fnstsw  %ax
    sahf
    jp  .L5
    je  .L2
    fstp    %st(0)
    jmp .L4
.L5:
    fstp    %st(0)
.L4:
    fldl    24(%esp)
    fstpl   (%esp)
    call    sqrt
.L2:
    fstpl   16(%esp)
    movl    $.LC1, %eax
    fldl    16(%esp)
    fstpl   4(%esp)
    movl    %eax, (%esp)
    call    printf
    movl    $0, %eax
    leave
    ret
    .size   main, .-main
    .section    .rodata
    .align 8
.LC0:
    .long   0
    .long   1073741824
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits

您可以看到,它发出的sqrt 函数的的电话。所以,你会得到一个链接错误,如果你不链接数学库。

You can see that it emits a call to the sqrt function. So you'll get a linker error if you don't link the math library.

案例2:用文字

    .file   "main.c"
    .section    .rodata
.LC1:
    .string "b = %lf\n"
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    fldl    .LC0
    fstpl   24(%esp)
    movl    $.LC1, %eax
    fldl    24(%esp)
    fstpl   4(%esp)
    movl    %eax, (%esp)
    call    printf
    movl    $0, %eax
    leave
    ret
    .size   main, .-main
    .section    .rodata
    .align 8
.LC0:
    .long   1719614413
    .long   1073127582
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits

有对没有调用sqrt 。因此,没有连接错误。

There's no call to sqrt. Hence no linker error.

随着优化,GCC会做不断的传播在这两种情况下。因此,没有连接错误在这两种情况下。

With optimizations on, GCC will do constant propagation in both cases. So no linker error in either case.

$ gcc main.c -save-temps
main.o: In function `main':
main.c:(.text+0x30): undefined reference to `sqrt'
collect2: ld returned 1 exit status
$ gcc main.c -save-temps -O2
$ 

这篇关于常量VS在数学库变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆