我从 math.h
库中的 round()
和 roundf()
函数得到了意想不到的结果。这是示例代码:
#include <stdio.h>
#include <math.h>
int main(void)
{
float f;
double d;
/* Note man page says that roundf() returns a float
and round() returns a double */
f = roundf(1.2);
d = round(1.2);
printf("%f\n", f);
printf("%lf\n", d);
return 0;
}
当我编译并运行程序时,我得到:
gcc -lm round.c
./a.out
288.000000
524288.000000
奇怪吧?
更新:连同答案,我已经确认代码在较新的编译器上可以正常工作。 (我认为 %lf 不是正确的 printf 说明符,但在这种情况下不会影响最终结果。)我需要弄清楚为什么编译器会以这种方式运行,因为我正在运行使用 round() 和一直在同一台机器上编译。我会在弄清楚后更新帖子。
gcc -v
Reading specs from /usr/lib/gcc-lib/i386-slackware-linux/2.95.3/specs
gcc version 2.95.3 20010315 (release)
最佳答案
如果编译代码时没有告诉 gcc 使用 C99 模式编译 (-std=c99
) 并且告诉它不知道“特殊内置”函数(使用 - fno-builtin
).然后它假设你的 round/roundf 函数被定义为
int round();
int roundf();
因为在 C99 以前的时代还没有这样的函数,所以它没有声明,然后隐式声明它们。这显然会失败,因为调用方将返回值视为 int,而被调用方(在链接库中那些函数的定义中)返回 float。例如,我得到这些结果:
[js@HOST2 cpp]$ ./a.out
1065353216.000000
-1048576.000000
[js@HOST2 cpp]$
并不是说您现在认为可以将返回值转换为 float 就可以了。好吧,情况更糟。甚至不能保证返回值与返回的 float 有任何关系。调用方从它知道返回整数的地方读取。但是你的编译器可能会从被调用方返回另一个地方的 float (比如,在一个 float 指针寄存器中)。上述实际上可以做任何事情,包括中止程序,因为它以未定义的方式运行。
那么,您可以做些什么来让它发挥作用呢?向编译器传递 std=c99
标志或使用其他不需要这些函数的舍入方式(floor 是其中之一)
gcc -std=c99 test.c -lm
请参阅man 3 round
的联机帮助页。但是,如果您有一个非常旧的 GCC - 我不确定它是否支持足够的 C99 来进行该切换。然后查看 round 联机帮助页中描述的功能测试宏。
关于c - 我如何错误地使用 C 中的 round() 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/575936/