为什么sqrt函数不适用于通过用户输入获取的值?

时间:2018-10-28 05:08:11

标签: c sqrt

以下代码:

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

int main(void)
{
    long long int a;
    scanf("%lld", &a);
    printf("%lf", sqrt(a));
    return 0;
}

给出输出:

source_file.c: In function ‘main’:
source_file.c:9:5: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]
     scanf("%lld", &a);
     ^
/tmp/ccWNm2Vs.o: In function `main':
source.c:(.text.startup+0x65): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

但是,如果我执行long long int a = 25;并删除scanf语句,或者只是执行sqrt(25),则它们都可以工作(正确地提供输出5.000000)。

我检查了this question,但是它用于C ++,并且使用函数重载,而afaict C没有函数重载(这就是为什么我们有sqrtfsqrt,{{1} }(如果我没看错)。此外,无论我采用sqrtl还是long long int类型的double,以上代码均失败。所以问题可能不相关。
另外,对于其他linked question,对于恒定定义的值,我也没有发生错误,相反,链接的问题正是这种情况。

那是什么原因?为什么常量值对a有效,而可变的用户输入值无效?

2 个答案:

答案 0 :(得分:4)

就像评论中提到的那样,您尚未针对libm进行链接,因此sqrt在链接时未定义。

  

为什么常量值对sqrt有效,而可变的用户输入值无效?

因为GCC将sqrt识别为builtin function,并且能够在编译时评估编译时常量的平方根,并且完全放弃了对sqrt的调用,因此避免了随后的链接器错误。

  

除非指定了sqrt(或-fno-builtin -fno-builtin-,否则ISO C90函数... function,...都被识别为内置函数。 是为单个功能指定的)。

如果要添加-fno-builtin-sqrt,则无论传递给sqrt的内容如何,​​都将看到链接器错误。

答案 1 :(得分:1)

stdlib.hstdio.h中的函数在libc.so中实现(对于静态链接,则为libc.a),默认情况下链接为可执行文件(就像{{1 }})。

可以指示GCC避免使用-lc-nostdlib选项进行自动链接。

math.h中的函数在-nodefaultlibs(或对于静态链接为libm.so)中具有实现,并且默认情况下未链接libm。

基本上,C ++运行时libm.a需要libstdc++,因此,如果使用GCC(g ++)编译C ++程序,则会自动获得libm的链接。