为什么sqrt()和abs()在C程序中工作而不包括math.h或stdlib.h?

Yos*_*Yos 2 c

下面是我在C中的一些代码.你可以看到我所包含的唯一标题是stdio.h.但是,我收到一个abs声明冲突的警告: note: 'abs' is a builtin with type 'int (int)'并且sqrt在不使用我的函数的情况下工作.

我的编译器版本:Apple LLVM version 8.0.0 (clang-800.0.42.1).

我正在使用的编译标志:-Wall -pedantic -ansi.

怎么会这样?

#include <stdio.h>

double abs(double x) {
    return x >= 0 ? x : -x;
}

double sqrt(double y) {
    double x = 1.0;
    int error;
    printf("My sqrt\n");
    if(y <= 0) {
        return 0;
    }
    while(abs(error = y - x * x) > .0005) {
        x = x + error/ (2 * x);
    }
    return x;

}

int main() {
    printf("sqrt(%d) = %8.3f\n", 2, sqrt(2.0));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Jim*_*mbo 11

像gcc这样的一些编译器有" 内置函数"(我认为有时称为"编译器内在函数"),我认为它们可以用于优化.这就是为什么你可以使用这些函数而不必链接libm.

编译器内在函数(有时称为"内置函数")就像您习惯使用的库函数,除非它们内置于编译器中.它们可能比常规库函数更快[参考]

从GCC页面(上面链接):

除非指定了-fno-builtin,否则ISO C90函数... abs,... sqrt,...都被识别为内置函数...所有这些函数都具有前缀为__builtin_的相应版本.

正如其他人所指出的,你也是自己宣布这些功能.您为这些函数命名的名称会与内置函数的名称"冲突".这就是为什么你看到note: 'abs' is a builtin with type 'int (int)'以及为什么当你删除你的功能时符号仍然有效.

  • 另一个难题:`sqrt`通常需要与libm(`-lm`)链接.但是`sqrt(2.0)`可以在编译时优化为`1.4142 ...`,因此不需要与libm链接. (4认同)