【发布时间】:2023-04-09 13:50:02
【问题描述】:
考虑以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
int main()
{
complex double aaa = INFINITY + 0*I;
printf("%.f + %.f*I\n", creal(aaa), cimag(aaa));
complex double bbb = 1.0/aaa;
printf("%.f + %.f*I\n", creal(bbb), cimag(bbb));
return EXIT_SUCCESS;
}
用gcc -std=gnu99 -lm编译,我希望输出是
inf + 0*I
0 + 0*I
这在 Linux 上是正确的(在带有 gcc 4.4.7 的 Scientific Linux 6.8、带有 gcc 5.3.1 的 Fedora 23 和带有 gcc 4.8.4 的 Ubuntu 14.04.5 上测试)。
但是,在 OS X(带有 clang-602.0.53 的 10.11.5)上,我得到了
inf + 0*I
南+南*我
很明显,clang 不符合 C99 标准(参见N1256,第 G.5.1 节;严格来说,这只是推荐的做法,而不是标准)。 事实上,clang 并没有定义宏 clang 是否故意做出这种行为? 更新:经过一些检查,我发现我测试的几个 Linux 环境也没有定义这个宏,但代码仍然在那里正常工作。__STDC_IEC_559_COMPLEX__,这个宏在 Sec. 中介绍。 G.1.
目前,我对跨平台支持的解决方法是检查宏
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
int main()
{
complex double aaa = INFINITY + 0*I;
printf("%.f + %.f*I\n", creal(aaa), cimag(aaa));
complex double bbb = 1.0/aaa;
#ifndef __STDC_IEC_559_COMPLEX__
if(isnan(bbb))
{
bbb = 0; //or do some trick that has to do with the problem context
}
#endif
printf("%.f + %.f*I\n", creal(bbb), cimag(bbb));
return EXIT_SUCCESS;
}
但我不确定它是否强大...有什么建议吗?
【问题讨论】:
-
C standard: INFINITY 扩展为浮点类型的常量表达式,表示正无穷或无符号无穷(如果可用);否则为在翻译时溢出的浮点类型的正常量。因此它的行为可能在不同平台上并不相同......
-
@EugeneSh。 1. 在这种情况下,
INFINITY确实会扩展为正无穷大,这可以通过输出的第一行或在调试器中进行检查; 2.这里我写INFINITY只是为了提供一个MWE。你可以在不改变结论的情况下写出像complex double aaa = 1.0/0.0;这样溢出来的东西; 3.如果这不起作用真的没有意义,因为我已经测试了double对应的对象(将所有complex double替换为double,去掉creal和cimag的功能,等)。 -
@LeoFang 它的数学处理方式和
printf()的表示方式可能并不完全相同。也许确定问题是否真的是clang或架构的最佳方法是使用gcc在OSX 上编译它。 -
这似乎是在较新版本中修复的 LLVM/Clang 问题。 LLVM/Clang 3.6.2(日期在
clang-602.0.53之后)具有预期的行为,而 LLVM/Clang 3.5.2 具有所描述的行为。 -
@kdhp,你是对的。在发布之前,我在 LLVM 3.6.0 (clang-602.0.53) 上进行测试,我刚刚在另一台运行 OS X 10.10.5 和 LLVM 3.7.0 (clang-700.1.81) 的机器上进行了测试,这给了我正确的结果。您可以发布答案,我会接受。谢谢!