C99 中复杂算术的类型安全

Type safety for complex arithmetic in C99

我正在使用 C 的复杂算术支持和 运行 一些令人惊讶和不受欢迎的行为。复数值似乎可以隐式转换为实数值,丢弃虚部。

考虑以下因素:

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

float complex getComplex(float real, float imag)
{
    return real + imag * I;
}

int main()
{
    const float /* missing complex! */ c = getComplex(25, 6) / getComplex(2, 4);
    printf("%f + %f J\n", crealf(c), cimag(c));
    return 0;
}

我希望收到一些警告,指出我正在将 float complex 分配给 float 或者可能在非复数值上调用 crealfcimagf,但这完全建立在 GCC 5.1 上,即使使用 -Wall -Wextra -Wconversion 开关也是如此。 Clang 3.6.1 至少会发出这样的警告:

wut.c:11:62: warning: implicit conversion discards imaginary component: '_Complex float' to 'float'
      [-Wconversion]
    const float /* missing complex! */ c = getComplex(25, 6) / getComplex(2, 4);
                                       ~   ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~

为什么复数 "collapse" 可以变成实数?标准中是否有关于此的一些措辞? GCC 是否有一些额外的开关可以提供有关此行为的警告?它已经困扰了我们,目前无法为此项目切换工具链(到 clang)。

C11 最终草案 (N1570),6.3.1.7 第 2 段:

When a value of complex type is converted to a real type, the imaginary part of the complex value is discarded and the value of the real part is converted according to the conversion rules for the corresponding real type.

实型是整型和浮点型。

C99 基本原理解释了这背后的动机:

In mathematics, when a complex is converted to real, the imaginary part is discarded. C99 follows the same convention.

并且(编号与 C11 相同):

The specification in §6.3.1.6 and §6.3.1.7 match Fortran's.