2

当我尝试从终端编译这个简单的代码时:

#include<stdio.h>

int main(void)
{

    printf("%f\n",sqrt(10));

    return 0;
}

使用

gcc main.c

命令,它被编译并且 a.out 给出正确的答案。这意味着数学函数被添加到自动链接的 C 标准库中。

但是,如果在 Eclipse IDE 中编译相同的代码而不向属性添加任何库,则会给出未定义的引用错误。这意味着数学函数不是 C 标准库的一部分。

真相是什么?

4

2 回答 2

6

您可能会在这里看到常量折叠,在数学函数调用中使用常量将导致编译器计算函数并一起省略对数学库的调用。

如果我们查看GCC 提供的其他内置函数的文档说(强调我的):

GCC 包括标准 C 库中许多函数的内置版本。即使您指定了 -fno-builtin 选项,带有 _ builtin前缀的版本始终被视为与 C 库函数具有相同的含义。(请参阅 C 方言选项)其中许多功能仅在某些情况下进行了优化;如果它们在特定情况下未优化,则会发出对库函数的调用。

如果我们看一下这个使用以下代码的稍微修改的实时示例:

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

int main(void)
{

    printf("%d\n",(int)sqrt(25));

    return 0;
}

我们看到以下程序集由gcc

movl    $5, %esi        
movq    %rax, %rdi
movl    $0, %eax
call    printf

所以我们看到在x64 abi5中是调用函数的第二个参数,是根本没有调用的结果。esisqrt(25)sqrt

请注意,您缺少:

#include <math.h>

更新

内置函数是gcc 的扩展,上面的内置链接解释了哪些是在哪种模式下使用的,它们都应该与标准函数具有相同的含义。

如果您担心您的代码是否符合标准,那么您可以查看手册的Options Controlling C Dialect部分。您可以使用-std来指定要遵守的标准,并-pedantic在使用不符合标准的功能时启用警告或-pedantic-errors使警告成为错误。所以例如使用

gcc -std=c99 -pedantic

当您使用符合C99标准的功能(例如零长度数组)时,会生成警告。

我们也可以-fno-builtin用来禁用一些内置函数,文档说:

不识别不以 _ builtin作为前缀开头的内置函数。有关受影响函数的详细信息,请参阅 GCC 提供的其他内置函数,包括那些在使用严格 ISO C 一致性的 -ansi 或 -std 选项时不是内置函数的函数,因为它们没有 ISO 标准含义。[...]

于 2013-10-07T17:18:38.887 回答
0

某些编译器标准库函数默认启用。编译时

int main(){

    printf("Hello World");
    return 0;
}  

此代码在 GCC 4.7.1 上编译并给出警告:

[Warning] implicit declaration of function 'printf' [-Wimplicit-function-declaration]  
[Warning] incompatible implicit declaration of built-in function 'printf' [enabled by default]
于 2013-10-07T17:18:51.597 回答