literal constant vs variable in math library

前端 未结 4 732
终归单人心
终归单人心 2020-12-03 19:34

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

4条回答
  •  遥遥无期
    2020-12-03 20:10

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

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

    Case 1: With the variable.

        .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
    

    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.

    Case 2: With the Literal.

        .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
    

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


    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
    $ 
    

提交回复
热议问题