有没有办法在不包含 <complex.h> 的情况下声明一个复数?
Is there a way to declare a complex number without including <complex.h>?
我想使用<complex.h>
库来加速一些计算,其中可能包含多达 20 个复杂元素和运算 (+ - * /)。但是,我的同事声明了一个结构:
struct complex {
double a;
double b;
};
因此,由于与上述结构冲突,无法使用来自库的complex
宏。
问题是,由于对当前项目的巨大影响,我无法更改结构的名称。我尝试改用 _Complex
宏,并删除了 #include <complex.h>
header,它起作用了,但 _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));
}
我希望有一种方法可以区分来自库的复杂宏和定义的复杂结构。遗憾的是我无法更改结构,所以事情变得出乎意料地复杂了。
我的 __STDC_VERSION__
是 201112L
,而 __VERSION__
是“4.2.1 兼容的 Apple LLVM 10.0.1 (clang-1001.0.46.4)”。
C 标准预料到了这个问题,并有一个专门针对它的条款,7.3.1p7:
Notwithstanding the provisions of 7.1.3, a program may undefine and perhaps then redefine the macros complex
, imaginary
, and I
.
这意味着,你可以这样做:
#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 complex
和 double _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
自动转换为 "compatible with"、double _Complex
,即使它们在内存中的布局可能相同。您将不得不手动来回复制。
或者您可以重新定义在 the_other_colleagues_header
中定义的结构体
#define complex my_complex
#include <the_other_colleagues_header>
#undef complex
#include <complex.h>
现在,在您的 .c 文件中,您可以同时使用 complex
和 my_complex
,而其他人仍然可以正常使用 struct complex
。或者为 complex.h
编写一个包装器并从您的应用程序中调用它
但更好的解决办法是让另一位同事改名。使用标准名称通常是个坏主意
你的实际问题是
my colleague has declared a struct:
struct complex {
double a;
double b;
};
解决这个问题。
解决这个问题的所有其他方法都会创建事实上对撤消标准C功能的未记录依赖 -宏的定义 complex
。您的组织要做的最好的事情可能就是 "On page 4 of our coding standards [you do have coding standards?], it states that you have to #undef complex
after you #include <complex.h>
, then you have to #include <stomps/on/complex.h>
after that"。您的组织实际做这么多的可能性有多大?然后确保计划中的每个人都知道这一点?
很可能,他们不会为此付出努力,他们甚至不会接近。
您将获得一些未记录的部落知识。
同样,您的组织是否有书面的编码标准,并实际执行它们?如果您不能对此做出肯定回答,那么您确实确实需要现在就真正解决问题的根本原因,而不是将其埋葬,等待将来造成更严重的问题。
struct complex
不仅创建了对撤消标准 C 功能的依赖,而且还创建了对 #include
指令和 #undef
语句的排序依赖。没有真正的方法可以知道如果不严格遵守这些依赖关系会发生什么 - 不能排除未来几年出现奇怪的结果和无法解释的故障。
是的,用 #undef complex
取消定义宏是合法的,而且并不难。但是,如果有人不这样做,或者以错误的顺序这样做,会发生什么?
如果您做得对,编写和维护软件已经够难的了。最好不要故意做一些有问题的事情,让程序的生命周期变得更难。
我想使用<complex.h>
库来加速一些计算,其中可能包含多达 20 个复杂元素和运算 (+ - * /)。但是,我的同事声明了一个结构:
struct complex {
double a;
double b;
};
因此,由于与上述结构冲突,无法使用来自库的complex
宏。
问题是,由于对当前项目的巨大影响,我无法更改结构的名称。我尝试改用 _Complex
宏,并删除了 #include <complex.h>
header,它起作用了,但 _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));
}
我希望有一种方法可以区分来自库的复杂宏和定义的复杂结构。遗憾的是我无法更改结构,所以事情变得出乎意料地复杂了。
我的 __STDC_VERSION__
是 201112L
,而 __VERSION__
是“4.2.1 兼容的 Apple LLVM 10.0.1 (clang-1001.0.46.4)”。
C 标准预料到了这个问题,并有一个专门针对它的条款,7.3.1p7:
Notwithstanding the provisions of 7.1.3, a program may undefine and perhaps then redefine the macros
complex
,imaginary
, andI
.
这意味着,你可以这样做:
#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 complex
和 double _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
自动转换为 "compatible with"、double _Complex
,即使它们在内存中的布局可能相同。您将不得不手动来回复制。
或者您可以重新定义在 the_other_colleagues_header
#define complex my_complex
#include <the_other_colleagues_header>
#undef complex
#include <complex.h>
现在,在您的 .c 文件中,您可以同时使用 complex
和 my_complex
,而其他人仍然可以正常使用 struct complex
。或者为 complex.h
编写一个包装器并从您的应用程序中调用它
但更好的解决办法是让另一位同事改名。使用标准名称通常是个坏主意
你的实际问题是
my colleague has declared a struct:
struct complex {
double a;
double b;
};
解决这个问题。
解决这个问题的所有其他方法都会创建事实上对撤消标准C功能的未记录依赖 -宏的定义 complex
。您的组织要做的最好的事情可能就是 "On page 4 of our coding standards [you do have coding standards?], it states that you have to #undef complex
after you #include <complex.h>
, then you have to #include <stomps/on/complex.h>
after that"。您的组织实际做这么多的可能性有多大?然后确保计划中的每个人都知道这一点?
很可能,他们不会为此付出努力,他们甚至不会接近。
您将获得一些未记录的部落知识。
同样,您的组织是否有书面的编码标准,并实际执行它们?如果您不能对此做出肯定回答,那么您确实确实需要现在就真正解决问题的根本原因,而不是将其埋葬,等待将来造成更严重的问题。
struct complex
不仅创建了对撤消标准 C 功能的依赖,而且还创建了对 #include
指令和 #undef
语句的排序依赖。没有真正的方法可以知道如果不严格遵守这些依赖关系会发生什么 - 不能排除未来几年出现奇怪的结果和无法解释的故障。
是的,用 #undef complex
取消定义宏是合法的,而且并不难。但是,如果有人不这样做,或者以错误的顺序这样做,会发生什么?
如果您做得对,编写和维护软件已经够难的了。最好不要故意做一些有问题的事情,让程序的生命周期变得更难。