1

我只是在学习 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' 的引用”。谢谢你。

4

3 回答 3

3

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

于 2012-09-17T04:21:23.213 回答
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 上已经有一个非常相似的问题。根据其接受的答案,

C++ 运行时 libstdc++ 需要 libm,因此如果您使用 GCC (g++) 编译 C++ 程序,您将自动获取 libm 链接。

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

于 2012-09-17T05:11:07.040 回答
1

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

编译器编译它就好了,因为您已经声明在某个地方定义了这个函数。编译后发生的步骤负责实际查找该函数定义。它被称为linking,并且在该阶段链接器查找这些定义。万一sqrtfoo它找不到任何东西,而万一sqrt它在某个标准库中找到它(我不知道这里的细节)。

于 2012-09-17T04:25:16.597 回答