C语言的pow函数无法处理变量指数

10
假设我有以下代码片段:
int i; double value;
for(i = 0; i < CONSTANT; i++) {
  value = (double)pow(2, i);
}

尝试编译此代码会出现“undefined reference to `pow'”错误。
无论包含还是不包含math.h,都没有区别,因为它最终仍然会被包含。
2.0提高到硬编码功率可以正常工作,但如果我用包含i的表达式替换指数,那么一切都会失败。
我做错了什么?谢谢。

你使用的编译器是什么?pow()还有其他可能的声明吗?你能准确地引用错误吗? - David Thornley
我正在使用GCC,没有其他关于pow的声明。问题肯定已经得到了答复;几乎所有的答案都帮了我一个大忙。但愿我能接受多个答案 :) 谢谢大家。 - user12163
5
其他人已经评论了为什么“pow”函数无法正常工作,但是使用“pow”函数本身就是代码的一个巨大问题。在C语言中,存在一个用于计算2的幂的操作符,它被称为“<<”。删除对“pow”函数的无效使用,改用“1<<i”,并且不要再使用“double”类型。 - R.. GitHub STOP HELPING ICE
这仅适用于 CONSTANT <= 32,或者可能需要使用long [long]来支持64位。 - zwol
pow 返回 double,所以强制转换 (double) 是无用的。 - phuclv
5个回答

16

这是一个非常有趣的行为,也是一个很好的学习例子。

要解决您的问题,请添加

-lm

如果你正在使用gcc编译器,可以将"-lm"参数添加到gcc命令行中。这会告诉编译器链接数学库。

看起来情况是这样的,如果你正在使用

pow(2.0, 3);
编译器意识到这个表达式的值是一个常量,因此只进行简单的替换操作。因此,不需要调用任何库函数。

这是我即将发布的解释。编译器也可以将 pow(n, 2) 优化为 n*n 或类似形式。 - zwol
1
事实上,作为后续评论...仅编译该循环,并进行最大优化(-O3),实际上可以在不使用 -lm 的情况下工作。这是因为该值没有被进一步使用,编译器只需展开和优化无用的循环和无用的 pow(),因此从未需要调用 libm 库中的 pow() 函数。 - qdot
编译器需要确定链接哪个函数才能进行此类优化,它是如何实现的呢? - jbulatek

3

您必须链接数学库:

gcc program.c -lm

原因在于GCC(和一些其他编译器)为文字常量内置了pow()函数。因此,如果您手动调用pow()并输入2.0,则编译器实际上会计算出答案并替换掉您的输入。对于变量输入,编译器必须依赖于数学库,您需要链接该库。


3

你需要使用-lm来链接数学库。

对于硬编码的值,它可以工作是因为编译器优化了pow调用。


1

pow 的代码是数学库的一部分。您需要链接该库(除了默认链接的C库)。

为此,在gcc中,编译器调用时指定-lm

gcc ... -lm

3
小小的警告:在命令行中,"-l"开关必须始终放置在所有目标文件之后。如果你不这样做,在某些Linux发行版上也许能够工作,但不应该依赖这种方式。 - zwol

0

http://www.cplusplus.com/reference/clibrary/cmath/pow/

在 C 语言中,只有接受两个 double 参数的版本使用了这个名称。其他重载版本仅在 C++ 中可用。
看起来你不能传递一个 int,所以只需将 i 声明为 double 类型即可解决问题。

“通常的算术转换”会在必要时将int转换为double。你正在错误的方向上努力。 - zwol
这是一个错误的答案,它回答了错误的问题。所以,是的。 - zwol
好的,这就是我在问题中所需要的答案。 - SixOThree

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接