在C ++中,为什么我不必包含任何使用sqrt()函数的东西?

时间:2012-09-17 04:19:46

标签: c++ include sqrt cmath

我只是在学习C ++。使用g ++版本3.2.3进行编译," g ++ hworld.cpp":

double sqrt(double);
int main(){
    double x = sqrt(1515.15);
    return 0;
}

编译好,但如果我们用" sqrtfoo"替换sqrt。编译器会说sqrtfoo不能用作函数。我以为我必须包括cmath,但我猜不是吗?有人可以在任何包含之前解释我的程序可以访问的内容吗?为了比较,gcc不允许我这样做,说"未定义引用' sqrt'。"谢谢。

3 个答案:

答案 0 :(得分:3)

您不需要包含cmath,因为您的代码已经有sqrt的原型,第一行。

答案 1 :(得分:2)

正如现有的答案所解释的那样,double sort(double)提供了一个原型,让编译器知道函数存在。

但是你也提到过这在GCC下不起作用。构建C或C ++程序时,源代码将编译为对象格式。然后将目标文件链接在一起以形成可执行文件。

要查看此操作,请尝试

gcc -c hello.c

这告诉GCC编译(-c)源文件hello.c。假设hello.c存在且没有错误,您将在当前目录中找到hello.o。现在试试

gcc -o hello hello.o

这告诉GCC将hello.o与相应的系统库链接,并生成一个名为“hello”的输出文件。如果hello.c使用数学函数,您还需要在数学库中链接:

gcc -o hello hello.o -lm

“ - l”用于告诉gcc包含额外的库(超出默认的“libc”C库)。 “m”指的是“libm”,它是包含sqrt的数学库。如果你的程序只使用一个源文件,那么通常会在一个命令中隐式地询问GCC编译和链接:

gcc -o hello hello.c -lm

现在回答你的问题。 GCC不会编译上面的代码,因为你没有要求它在数学库中链接。但是g ++没问题。 Stack Overflow上已经有一个非常similar question。根据其接受的答案,

  

C ++运行时libstdc ++需要libm,所以如果你编译一个C ++   使用GCC程序(g ++),您将自动获得libm链接。

由于“libstdc ++”是C ++语言运行时库,因此默认情况下它包含在g ++中。由于它依赖于libm,链接器会在生成最终二进制程序时自动加载libm。

答案 2 :(得分:1)

头文件仅包含声明(签名),并且您在第一行中包含了一个(原型:double sqrt(double))。

编译器编译它就好了,因为你已经说过定义了这个函数。编译后发生的步骤负责实际查找该函数定义。它被称为linking,在此阶段,链接器会查找这些定义。如果sqrtfoo找不到任何内容,而sqrt则会在某个标准库中找到它(我不知道这里的详细信息)。