ceil()仅适用于右值

时间:2019-06-07 10:56:30

标签: c gcc shared-libraries

我正在尝试在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

我缺少什么?

2 个答案:

答案 0 :(得分:1)

使用以下行进行编译:

gcc -std=c99 main.c -o main -lm

(在-lm之后放-o main

请参见https://stackoverflow.com/a/11894098/4030665

答案 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将起作用。