1

当我编译下面的精简程序时,我从链接器收到以下错误:

$ gcc -std=c99 -O3 powltest.c -o powltest
/tmp/ccYkWTGI.o: In function `main':
powltest.c:(.text+0x7a): undefined reference to `powl'
collect2: ld returned 1 exit status

如果我用 注释掉该行sscanf(),则编译成功,并且在功能减少的情况下程序可以正确运行。如果我改为注释掉包含的行,它也可以工作powl()

#include <stdio.h>
#include <math.h>

int main(int argc, char *argv[])
{
    unsigned int bits = 5;
    unsigned int n = 0;
    unsigned long long start = 0;

    n = sscanf(argv[1], "%u", &bits);
    printf("%u\n", bits);
    start = powl(2, bits) - 1;
    printf("%llu\n", start);
}

以下是版本:

$ gcc --version
gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1
$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.20

相同的结果:

$ gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-51)
$ ld --version
GNU ld version 2.17.50.0.6-14.el5 20061020

运行:

$ ./powltest 42    # commented-out sscanf()
5
31
$ ./powltest 42    # commented-out powl()
42
0

我究竟做错了什么?

4

2 回答 2

6

当您注释掉sscanf调用时,所有变量都具有在编译时已知的值,并且编译器的优化器能够确定调用的结果,而powl无需实际调用中声明的任何函数math.h

当您取消注释scanf调用时,优化器无法在编译时确定powl调用的结果,因此它必须调用真正的powl函数,该函数位于一个单独的库中,您必须使用-lm.

于 2012-01-05T03:59:22.400 回答
3

与数学库 ( -lm) 链接可消除undefined reference to 'powl'错误:

gcc -o test test.c -lm

这在手册页中也有说明powl

概要

#include <math.h>

double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);

与 -lm 链接。

编辑:它只在sscanf被注释掉时才为我编译,如果它也用优化(-OX)编译,dreamlax在他的回答中有原因。

于 2012-01-05T03:52:23.773 回答