有没有一种方法可以声明一个不包含<complex.h>的复数?

thn*_*ghh 0 c c99 standard-library header-files complex-numbers

我想使用该<complex.h>库来加速某些计算,其中可能包括多达20个复杂元素和运算(+-* /)。但是,我的同事声明了一个结构:

struct complex {
    double a;
    double b;
};
Run Code Online (Sandbox Code Playgroud)

因此,complex由于与上述结构冲突,无法使用来自库的宏。

事实是,由于对当前项目的巨大影响,我无法更改结构的名称。我尝试使用_Complex宏来代替,并取出#include <complex.h>头,它的工作,但_Imaginary_I_Complex_I还是I不起作用。

#include <stdio.h>      /* Standard Library of Input and Output */
// #include <complex.h>    /* I want to remove this */    

int main() {
    struct complex
    {
        double a;
        double b;
    };
    double _Complex z1 = 1.0;// + 3.0 * _Complex_I;
    double _Complex z2 = 1.0;// - 4.0 * _Complex_I;    

    // none of these work
    double _Complex z = CMPLX(0.0, -0.0);
    double _Complex z3 = 1.0 + 1.0 * _Imaginary_I;
    double _Complex z4 = 1.0 + 1.0 * _Complex_I;
    double _Complex z5 = 1.0 + 1.0 * I;    

    printf("Starting values: Z1 = %.2f + %.2fi\n", creal(z1), cimag(z1));    

}
Run Code Online (Sandbox Code Playgroud)

我期望有一种方法可以区分来自库的复杂宏和定义的复杂结构。可悲的是,我无法更改结构,因此事情变得异常复杂。

__STDC_VERSION__201112L,而我是__VERSION__“ 4.2.1兼容Apple LLVM 10.0.1(clang-1001.0.46.4)”。

zwo*_*wol 8

C标准预见到了这个问题,并为此专门提供了一个条款7.3.1p7

尽管有7.1.3的规定,程序可能取消定义,也许再重新定义宏compleximaginaryI

这意味着,您可以执行以下操作:

#include <stdio.h>
#include <complex.h>
#undef complex     /* after including complex.h, before declaring struct complex */

//#include <header_that_defines_struct_complex.h>
struct complex
{
    double a;
    double b;
};
Run Code Online (Sandbox Code Playgroud)

现在,您的代码可以同时使用struct complexdouble _Complex没有问题,并且可以访问中声明的复杂数学函数<complex.h>

int main(void)
{
    // this should all be fine now
    double _Complex z = CMPLX(0.0, -0.0);
    double _Complex z1 = 1.0 + 3.0 * _Complex_I;
    double _Complex z2 = 1.0 - 4.0 * _Complex_I;    
    double _Complex z3 = 1.0 + 1.0 * _Imaginary_I;
    double _Complex z4 = 1.0 + 1.0 * _Complex_I;
    double _Complex z5 = 1.0 + 1.0 * I;    
    printf("Starting values: Z1 = %.2f + %.2fi\n", creal(z1), cimag(z1));    

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是请注意,即使它们在内存中可能具有相同的布局struct complex,也无法使其自动转换为或与之“兼容” double _Complex。您将需要手动来回复制。

  • 虽然这是目前规避标准定义的有效方法,但这并不能为未来的软件开发奠定坚实的基础。一般来说,重用 C 标准为不同目的定义的任何标识符并不是一个好主意。仅供参考,C 委员会目前正在讨论将这些丑陋的关键字(如“_Complex”)更改为“真正的”小写名称。 (2认同)