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

Why does sqrt function not work for values taken through user input?

以下代码:

#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 没有函数重载(这就是为什么我们有 sqrtfsqrtsqrtl 如果我没记错的话)。此外,无论我采用 long long int 还是 double 类型的 a,上述代码都会失败。所以,问题可能不相关。
此外,关于另一个 linked question,对于不断定义的值,我没有发生错误,而恰好是链接问题的情况。

那是什么原因呢?为什么常量值适用于 sqrt,而可变用户输入值则不行?

就像评论中提到的那样,您没有 link反对 libm 所以 sqrt 在 link 时未定义。

Why would a constant value work for sqrt, while a variable user input value won't?

因为 GCC 将 sqrt 识别为 builtin function 并且能够在编译时计算编译时常量的平方根,并完全放弃对 sqrt 的调用,从而避免随后的 linker 错误。

The ISO C90 functions ... sqrt, ... are all recognized as built-in functions unless -fno-builtin is specified (or -fno-builtin-function is specified for an individual function).

如果您要添加 -fno-builtin-sqrt,无论您将什么传递给 sqrt,您都会看到 linker 错误。

stdlib.hstdio.h 中的函数在 libc.so 中有实现(或 libc.a 用于静态 linking),即 link默认进入可执行文件(就像指定了 -lc)。

可以指示 GCC 使用 -nostdlib-nodefaultlibs 选项避免这种自动 link。

math.h 中的函数在 libm.so 中有实现(或 libm.a 用于静态 linking),默认情况下不 link 编辑 libm .

基本上,C++ 运行时 libstdc++ 需要 libm,所以如果你用 GCC (g++) 编译 C++ 程序,你会自动得到 libm linked .