我怎么在C中错误地使用round()函数?

时间:2009-02-22 22:15:45

标签: c

我从round()库中的roundf()math.h函数获得了意外结果。以下是示例代码:

#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

Wierd嗯?

更新:除了答案之外,我还确认代码在较新的编译器上正常运行。 (我认为%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)

7 个答案:

答案 0 :(得分:11)

如果编译代码而不告诉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有任何关系。调用端从一个知道返回整数的位置读取。但是你的编译器可能会从被调用方返回另一个地方(例如浮点指针寄存器中)的浮点数。上面实际上可以做任何事情,包括中止程序,因为它的行为方式不确定。

那么,你能做些什么让它发挥作用?传递编译器std=c99标志或使用其他方式进行舍入(floor是其中之一),不需要这些函数

gcc -std=c99 test.c -lm

请参阅man 3 round的联机帮助页。但是,如果你有一个非常老的GCC - 我不确定它是否支持足够的C99来进行那个转换。然后查看圆形联机帮助页中描述的功能测试宏。

答案 1 :(得分:3)

当我编译并运行这个确切的代码(在cygwin上的gcc下)时,我得到:

$ ./a.exe
1.000000
1.000000

您的编译器有多新?我只能想到编译器错误,因为gcc -Wall也没有发出任何警告。

要添加一些更多信息,this forum thread似乎表明将编译器更改为更新的版本会修复它。如果这对您不起作用,您需要提供有关编译器和操作系统的更多详细信息,但鉴于这似乎适用于三个不同平台上的其他人,看起来您的编译器有问题。

答案 2 :(得分:2)

为了增加批准的合唱,这对我来说很好(OS X Leopard使用gcc)。

出于好奇,你需要使用-lm标志吗?我没有第一次,我第二次做了,没有区别,但那是因为libm.dylib和libc.dylib是OS X上同一个库的符号链接。也许你的libm坏了或什么?你需要链接到libm吗?我认为math.h函数将成为libc的一部分......?

编辑:

在您执行任何操作之前,请尝试使用此选项:

float f = 0;
double d = 0;

我认为不应该改变任何东西,但如果确实如此,我就赢了。

答案 3 :(得分:2)

在Ubuntu上使用gcc版本4.3.2再一次“在我的机器上运行”。

$ ./a.out
1.000000
1.000000

我编译时会收到一些警告。

$ gcc -lm round.c
round.c: In function ‘main’:
round.c:11: warning: incompatible implicit declaration of built-in function ‘roundf’
round.c:12: warning: incompatible implicit declaration of built-in function ‘round’

答案 4 :(得分:2)

litb走在正确的轨道上。 -std=c99无效,但添加#define _ISOC99_SOURCE有效。所以代码看起来像:

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

int main(void)
{
...

答案 5 :(得分:1)

这显然无济于事,但代码看起来像我预期的那样运行。一切似乎都很好。

答案 6 :(得分:0)

看起来你正确使用它,描述你的环境吗?