gcc和math.h的奇怪行为?

jte*_*ori 8 c math pow

我一直在尝试构建一些使用数学函数的代码(例如pow).

math.h包含,并-lm在构建期间使用该标志.

当像这样调用编译时(-lm命令开头的标志),它失败了,说有一个未定义的引用pow:

gcc -lm -O3 main.o clustering.o grassberger.o hash.o list.o mat.o metropolis.o motif_ids.o output.o permutation.o prob.o random.o results.o role.o stubs.o switches.o -o mfinder
main.o: In function `get_sn_motif_id':
main.c:(.text+0x28d): undefined reference to `pow'
Run Code Online (Sandbox Code Playgroud)

-lm国旗放在命令的末尾时,它就可以了!

gcc -O3 main.o clustering.o grassberger.o hash.o list.o mat.o metropolis.o motif_ids.o output.o permutation.o prob.o random.o results.o role.o stubs.o switches.o -o mfinder -lm
Run Code Online (Sandbox Code Playgroud)

这是正常的吗?

NPE*_*NPE 18

是的,这是正常的.对于许多链接器,指定目标文件和库的顺序很重要.

引用"GCC简介 - 用于GNU编译器gcc和g ++":

链接器的传统行为是在命令行中指定的库中从左到右搜索外部函数.这意味着包含函数定义的库应该出现在使用它的任何源文件或目标文件之后.这包括使用快捷方式-l选项指定的库,如以下命令所示:

$ gcc -Wall calc.c -lm -o calc (correct order)

这种行为很常见,但绝不是普遍的.如有疑问,最好查阅链接器手册.例如,在我的Ubuntu系统上man ld声明:

   -l namespec
   --library=namespec

       ...

       The linker will search an archive only once, at the location where
       it is specified on the command line.  If the archive defines a
       symbol which was undefined in some object which appeared before the
       archive on the command line, the linker will include the
       appropriate file(s) from the archive.  However, an undefined symbol
       in an object appearing later on the command line will not cause the
       linker to search the archive again.
Run Code Online (Sandbox Code Playgroud)

换句话说,这个链接器确实以gcc书中描述的方式运行.