我正在尝试在ubuntu 18.04(64位)中编译该程序:
#include <math.h>
#include <stdio.h>
int main() {
double x = 1.9;
float y = 1.8;
int x2 = ceil(x);
int y2 = ceil(y);
printf("%d, %d\n", x2, y2);
return 0;
}
我正在使用的gcc
命令是:
gcc -std=c99 -lm main.c -o main
我得到的错误是:
/tmp/ccWL94J9.o: In function `main':
main.c:(.text+0x30): undefined reference to `ceil'
main.c:(.text+0x41): undefined reference to `ceil'
collect2: error: ld returned 1 exit status
尽管,例如,如果我将ceil(x)
替换为ceil(1.2)
,并且与ceil(y)
类似,我可以构建并执行程序。
此外,我检查了是否确实安装了libm.so
:
bash> find /usr/lib -name "*libm.so*"
/usr/lib/x86_64-linux-gnu/libm.so
我缺少什么?
答案 0 :(得分:1)
使用以下行进行编译:
gcc -std=c99 main.c -o main -lm
(在-lm
之后放-o main
)
答案 1 :(得分:0)
使用某些表达式E
,尤其是常量,编译器可以在编译时评估ceil(E)
,如果不禁用此优化,则可以这样做。然后,编译器生成使用该结果且不调用ceil
的代码。当编译器在编译期间无法评估ceil(E)
时,它将生成调用ceil
的代码。
开关-lm
是标准数学库的缩写。链接器按照输入文件在命令行中出现的顺序处理输入文件。链接器处理库时,它将从库中提取所有对象模块,这些对象模块包含正在构建的可执行文件(或其他输出)中当前需要(引用但未定义)的符号的定义。
GCC在其命令行上维护各个单元的顺序。给定-lm main.c
,它会编译main.c
以产生一个对象模块,然后按顺序将-lm
和对象模块传递给链接器。由于数学库是第一个,因此当链接程序对其进行处理时,它尚未看到引用它的任何符号,因此它不会从该库中获取任何模块。
如果改为给GCC main.c -lm
,则链接器将在main
对象模块之后处理数学库。然后,当链接程序处理数学库时,它将知道main
引用了ceil
,因此它将从数学库中提取定义ceil
的模块。
因此,gcc -std=c99 -lm main.c -o main
将与仅使用常量ceil
的源代码一起工作,但不适用于示例中的源代码,而gcc -std=c99 main.c -lm -o main
将起作用。