为什么在下面的代码中“if (sqrt)”条件总是正确的?编译时,gcc 会发出这样的警告,
weak.c: In function âfâ:
weak.c:6: warning: the address of âsqrtâ, will always evaluate as âtrueâ
源码,</p>
#include <stdio.h>
extern double sqrt(double x); /* DECLARATION VERSION 1 */
/* extern double sqrt(double x) __attribute__ ((weak)); */ /* DECLARATION VERSION 2 */
void f() {
if (sqrt) {
printf("sqrt of 10 %f \n", sqrt(10.0));
}
else {
printf("sqrt not found \n");
}
}
int main (int arg, char **argv)
{
f();
return 0;
}
如果我注释掉行-“声明版本 1”并取消注释行-“声明版本 2”,我有一个具有以下行为的二进制文件。
- 当二进制文件与 -lm 链接时,“if (sqrt)”为真。
- 如果不是,则条件为假。我知道/认为对于一个弱符号,这里是“sqrt”函数,链接时它被初始化为 0。因此,当“sqrt”符号在其他地方(库)找不到它的定义时,“if (sqrt)”条件为假。
但是,当我使用“声明版本 1”时,为什么“sqrt”总是非零?在“DECLARATION VERSION 1”中,“sqrt”不是弱符号,当然也不是强符号。实际上,当您使用“nm”命令时,您找不到“sqrt”符号。更重要的是,当我尝试打印“sqrt”的地址时,我得到一个编译错误。
有人知道“sqrt”不为零的原因吗?
提前致谢!
由于我找不到合适的标题来描述我的问题,如果有的话,请建议一个更好的标题。
我想我找到了原因:
gcc 有一个用于优化目的的内置 sqrt() 函数。如果可能,gcc 将用其内置的 sqrt() http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html替换 libm 中对 sqrt() 的调用。编译时,如果未关闭内置函数且未给出 libm(-lm),gcc 将使用其内置版本的 sqrt(),它始终具有非零地址。当我关闭内置时,我得到一个编译错误,
$ gcc -fno-builtin weak.c
weak.c: In function âfâ:
weak.c:9: warning: the address of âsqrtâ, will always evaluate as âtrueâ
/tmp/cc84fwK9.o: In function `f':
weak.c:(.text+0x11): undefined reference to `sqrt'
weak.c:(.text+0x29): undefined reference to `sqrt'
collect2: ld returned 1 exit status