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

时间:2019-05-17 16:31:36

标签: c header-files c99 complex-numbers standard-library

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

struct complex {
    double a;
    double b;
};

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

问题是,由于对当前项目的巨大影响,我无法更改结构的名称。我尝试改用_Complex宏,并删除了#include <complex.h>标头,但它起作用了,但是_Imaginary_I_Complex_II不起作用。

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

}

我期望有一种区分库中的复杂宏和定义的复杂结构的方法。遗憾的是我无法更改结构,所以事情变得异常复杂。

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

3 个答案:

答案 0 :(得分: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;
};

现在,您的代码可以毫无问题地使用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;
}

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

答案 1 :(得分:2)

或者,您可以重新定义the_other_colleagues_header

中定义的结构复合体
#define complex my_complex
#include <the_other_colleagues_header>
#undef complex

#include <complex.h>

现在,在.c文件中,您可以同时使用complexmy_complex,其他人仍可以照常使用struct complex。或为complex.h写一个包装,然后从您的应用中调用

但是更好的解决方案是要求其他同事更改名称。使用标准名称通常是个坏主意

答案 2 :(得分:2)

您的实际问题是

my colleague has declared a struct:

    struct complex {
        double a;
        double b;
    };

解决此问题。

解决该问题的所有其他方式将导致事实上未记录的依赖,撤销标准C功能-宏{{1的定义}}。您的组织要做的最好的事情可能是“在我们的编码标准的第4页[您有编码标准吗?],它指出您必须在complex之后#undef complex,然后您之后必须#include <complex.h>”。您的组织实际上能做到的几率是多少?然后确保程序中的每个人都知道吗?

最有可能的是,他们不会为此付出努力,甚至不会接近。

您将获得一些未记录的部落知识。

再次,您的组织是否有书面的编码标准,并且实际执行它们?如果您不能同意,那么您确实确实需要立即解决问题的根本原因,而不是将其埋藏,以免将来引起更严重的问题。

#include <stomps/on/complex.h>不仅创建了撤消标准C功能的依赖关系,而且还创建了对struct complex指令和#include语句的排序依赖关系。没有真正的方法知道如果不严格遵循这些依赖关系会发生什么-无法排除未来几年的奇怪结果和无法解释的故障。

是的,使用#undef取消宏的定义是合法的,而不是那么困难。但是当某人不这样做或这样做顺序错误时会发生什么情况?

正确地编写和维护软件就很难了。故意做充其量可疑的事情,不要在程序的整个生命周期中加倍费力。