gcc编译含math.h程序的奇怪现象(并非未添加-lm)
Powered by lihux @ ustc
最近学习linux下编程时发现一个小问题:
一个最简单的main.c程序
#include<math.h>
#include<stdio.h>
int main()
{
double a = 4;
sqrt(a);
return 0;
}
如果使用gcc而非g++编译的话,直接使用命令:
#gcc -o a main.c
编译会提示未找到sqrt的定义,这个是因为缺少了“-lm”:必须要显示的调用libm.so动态库;
但是现在,有一种情况直接通过
#gcc -o a main.c
来编译而不报错的情况:即把sqrt(a)改成sqrt(4)!
在CSDN上请教了高手之后说是编译器直接计算sqrt(4)了,可以看汇编代码,本该调用函数的地方是一个mov ,而未使用libm.so中的sqrt()函数,自然也就可以编译通过了。于是我就通过设计一个测试程序,然后编译成汇编文件.s,查看:
/************************************
void math()
{
double a = sqrt(4.23);
}
void matha()
{
double a = 4.23;
sqrt(a);
}
/************************************
编译成汇编文件后得到对应的代码分别为:
/***************************************
.globl math
.type math, @function
math:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
fldl .LC0
fstpl -8(%ebp)
leave
ret
.size math, .-math
.globl matha
.type matha, @function
matha:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
fldl .LC2
fstpl -16(%ebp)
fldl -16(%ebp)
fsqrt
fucomp %st(0)
fnstsw %ax
sahf
jp .L6
je .L5
.L6:
fldl -16(%ebp)
fstpl (%esp)
call sqrt
fstp %st(0)
.L5:
leave
ret
.size matha, .-matha
/*****************************************
代码虽然不是全懂,但一经对比就会发现,sqrt(a)的汇编代码确实是有调用:“call sqrt”,而sqrt(4.23)则没有。由于gcc 相比于g++无法自动连接C++库,使用gcc编译必须加“-lm”,而g++则不必,所以我们平时编译程序的时候应优先选择g++。
问题找到了之后,不禁感慨,居然是聪明的编译器在其中做了手脚,没有经验的人怎可能看的出来呢?看来,内功还要继续练习啊。