2009-02-22 176 views
7

我越来越从round()roundf()功能意想不到的结果在math.h库。下面是示例代码:我如何错误地使用C中的round()函数?

#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; 
} 

当我complie并运行该程序,我得到:

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) 
+0

我不明白为什么。它在我的情况下输出1.000000。 – tvanfosson 2009-02-22 22:24:22

+0

Upvoted抵消downvote。这是一个完全有效的问题。如果我有这种行为,我也会问这个问题。 – 2009-02-22 22:31:48

+0

请更新您的编译器。 GCC 2.95.3它已经8岁了......这些年来已经修复了数百万的错误。 – 2009-02-22 23:04:13

回答

10

如果编译代码而不告诉gcc编译C99模式(-std=c99)并告诉它不知道“特殊内建”函数(使用​​),则可能会失败。然后它假定您一轮/ roundf功能是因为在预C99倍定义为

int round(); 
int roundf(); 

没有这样的功能呢,所以它没有一个声明,隐式声明它们然后。这显然会失败,因为调用方将返回值视为int,而被调用方(在链接库中这些函数的定义中)返回一个浮点数。我得到这些结果,例如:

[[email protected] cpp]$ ./a.out 
1065353216.000000 
-1048576.000000 
[[email protected] cpp]$ 

不是说你,现在你可以在返回值转换为浮动,并确定认为。呃,情况更糟。返回值甚至不保证与返回的浮点数有关。调用方从它知道返回整数的位置读取数据。但是你的编译器可能会在被调用方的另一个地方(比如说,在一个浮点指针寄存器中)返回浮点数。上面实际上可以做任何事情,包括中止程序,因为它的行为不明确。

那么,你能做些什么来使它工作?通过编译器std=c99标志或使用其他方式来圆(地板就是其中之一),它不需要这些功能

gcc -std=c99 test.c -lm 

man 3 round手册页。但是,如果你有一个非常古老的GCC - 我不确定它是否支持足够的C99来进行切换。查看当时的联机帮助页中描述的功能测试宏。

3

当我编译并(在Cygwin的下GCC)运行这个确切的代码我得到:

$ ./a.exe 
1.000000 
1.000000 

有多新的编译器?编译器错误是我能想到的,因为gcc -Wall也不会给出任何警告。

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

+0

我确实让它在更新的编译器上工作。由于我的情况,我可以升级编译器。 – Harry 2009-02-22 22:32:51

1

这显然不利于但代码看起来和运行如预期的我。一切似乎都很好。

2

要添加到审批的合唱,这工作得很好,我(OS X Leopard的使用gcc)。

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

编辑:

你做任何在此之前,请尝试使用这个:

float f = 0; 
double d = 0; 

我不认为应该改变什么,但如果这样做,我赢了。

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’ 
0

看起来你使用得很好,描述一下你的环境?

2

litb在正确的轨道上。 -std=c99没有工作,但加入#define _ISOC99_SOURCE工作。所以代码如下所示:

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

int main(void) 
{ 
...