4

有人能解释一下为什么下面的代码为 test4 变量产生与其他 3 个不同的输出吗?我已经用 gcc 版本 4.2.1 和 4.5.3(以及介于两者之间的其他版本)对此进行了检查。

也许我遗漏了一些明显的东西,但它看起来很简单......

#include <stdio.h>
#include <complex.h>

main()
{
    double complex test1, test2, test3, test4;

    test1 = 81141117.0;
    test2 = 81141117.0 + I * 0;
    test3 = 81141117 + I * 0.0;
    test4 = 81141117 + I * 0;
    printf("%ld + %ld I, %ld + %ld I, ", (long)creal(test1), (long)cimag(test1), (long)creal(test2), (long)cimag(test2));
    printf("%ld + %ld I, %ld + %ld I\n", (long)creal(test3), (long)cimag(test3), (long)creal(test4), (long)cimag(test4));
}

输出:

81141117 + 0 I, 81141117 + 0 I
81141117 + 0 I, 81141120 + 0 I

似乎只有整数项的 test4 被提升为浮点数而不是声明的双精度数,并且四舍五入开始发挥作用。

4

1 回答 1

4

我已经在 Mac OS X 10.7.5(自制 GCC)上测试了 GCC 4.7.1,以及提供的系统/usr/bin/gcc/usr/bin/clang,它们都产生了与您报告的结果相同的结果。

我同意您的分析,即当复数float的两个项都表示为整数时,必须进行转换。doubleC 2011 标准包括以下示例:

ISO/IEC 9899:2011 §6.7.9 初始化

¶24 示例 1 如果<complex.h>已经#included,则声明

int i = 3.5;
double complex c = 5 + 3 * I;

用值 3 定义和初始化 i,用值 5. 0 + i3 初始化 c。0。

这清楚地表明您应该能够编写整数表达式并获得有效的double complex(尽管示例是非规范性的)。float但是,它没有解决在转换为之前是否应将整数值转换为double,但语言中没有其他地方可以自动执行此操作(显然,您可以强制它),因此不太可能是预期的解释。

总的来说,我认为这很可能是一个可以报告给 GCC 团队的错误(这不是我提倡的轻率行为)。如果您运行gcc --help,则输出以以下消息结尾:

For bug reporting instructions, please see:
<http://gcc.gnu.org/bugs.html>

我将扩展您的示例,如下所示(或者,我确实扩展了您的示例,如下所示):

#include <stdio.h>
#include <complex.h>

int main(void)
{
    double complex test1, test2, test3, test4, test5, test6, test7, test8;

    test1 = 81141117.0;
    test2 = 81141117.0 + I * 0;
    test3 = 81141117 + I * 0.0;
    test4 = 81141117 + I * 0;
    test5 = (float)81141117 + I * 0;
    test6 = 81141117 + I * (float)0;
    test7 = 81141117.F + I * 0;
    test8 = 81141117 + I * 0.F;
    printf("%ld + %ld I, %ld + %ld I\n", (long)creal(test1), (long)cimag(test1), (long)creal(test2), (long)cimag(test2));
    printf("%ld + %ld I, %ld + %ld I\n", (long)creal(test3), (long)cimag(test3), (long)creal(test4), (long)cimag(test4));
    printf("%ld + %ld I, %ld + %ld I\n", (long)creal(test5), (long)cimag(test5), (long)creal(test6), (long)cimag(test6));
    printf("%ld + %ld I, %ld + %ld I\n", (long)creal(test7), (long)cimag(test7), (long)creal(test8), (long)cimag(test8));
}

我得到的输出是:

81141117 + 0 I, 81141117 + 0 I
81141117 + 0 I, 81141120 + 0 I
81141120 + 0 I, 81141120 + 0 I
81141120 + 0 I, 81141120 + 0 I

如您所见,最后两行有显式(float)强制转换或显式浮点常量,产生的结果与有问题的行相同(但值是合法的)。

您可能(或可能不)想尝试使用CMPLX, CMPLXF(也可能是CMPLXL)宏;如果它们为某些“有趣”的定义产生了“有趣”的值,我只会将它们添加到报告的示例中。


编译器版本号:

$ /usr/gcc/v4.7.1/bin/gcc --version
gcc (GCC) 4.7.1
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ /usr/bin/gcc --version
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang --version
Apple clang version 4.1 (tags/Apple/clang-421.11.65) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin11.4.2
Thread model: posix
$
于 2012-11-28T07:03:05.290 回答