与Visual Studio的C99复杂的支持
-
21-08-2019 - |
题
我想用复数如C99中定义,但我需要支持不支持它的编译器(MS的编译器来记)。
我不需要很多的功能,并在编译器实现所需的功能,而不支持不是太困难。但我有一个很难实现的“类型”本身。理想情况下,我想这样做:
#ifndef HAVE_CREAL
double creal(complex z)
{
/* .... */
}
#endif
#ifndef HAVE_CREALF
float creal(float complex z)
{
/* ... */
}
#endif
但我不知道我看看如何做到这一点,如果编译器无法识别“浮动情结”。我真的认为这是不可能的,但C库通过 Dinkumware的似乎另有指示。解决办法是什么 ?我不介意使用函数/宏的类型的操作,但我需要一种方式来赋值给一个复数,并取回的方式whichi与C99兼容它的真正/虚部。
解决方案
最后我做这样的事情:
#ifdef USE_C99_COMPLEX
#include <complex.h>
typedef complex my_complex;
#else
typedef struct {
double x, y;
} my_complex;
#endif
/*
* Those unions are used to convert a pointer of my_complex to native C99
* complex or our own complex type indenpendently on whether C99 complex
* support is available
*/
#ifdef USE_C99_COMPLEX
typedef union {
my_complex my_z;
complex c99_z;
} __complex_to_c99_cast;
#else
typedef union {
my_complex my_z;
my_complex c99_z;
} __complex_to_c99_cast;
#endif
为类型定义,并且如下来定义一组复杂的功能:
#ifndef HAVE_CREAL
double my_creal(my_complex z)
{
union {
my_complex z;
double a[2];
} z1;
z1.z = z;
return z1.a[0];
}
#endif
#ifdef HAVE_CREAL
my_complex my_creal(ny_complex z)
{
__complex_to_c99_cast z1;
__complex_to_c99_cast ret;
z1.my_z = z;
ret.c99_z = creal(z1.c99_z);
return ret.npy_z;
}
#endif
这是有点复杂,但这种使我容易地重用可用的当C LIB的功能,并且它可以通过码发生器被部分地自动的。
解决方案
不管你做什么,你不能让“漂浮情结”在非C99编译器正确解析。因此,而不是书面的,使一些类型定义。这是,如果你只需要支持一个复杂类型容易得多,所以我就用float complex
证明。
首先,定义类型:
#if __STDC_VERSION__ >= 199901L
//using a C99 compiler
#include <complex.h>
typedef float _Complex float_complex;
#else
typedef struct
{
float re, im;
} float_complex;
#endif
然后,我们需要能够创建复杂的数字和模拟creal和cimag。
#if __STDC_VERSION__ >= 199901L
//creal, cimag already defined in complex.h
inline complex_float make_complex_float(float real, float imag)
{
return real + imag * I;
}
#else
#define creal(z) ((z).re)
#define cimag(z) ((z).im)
extern const complex_float complex_i; //put in a translation unit somewhere
#define I complex_i
inline complex_float make_complex_float(float real, float imag)
{
complex_float z = {real, imag};
return z;
}
#endif
接下来,写函数涡卷加法,减法,乘法,除法,和比较
#if __STDC_VERSION__ >= 199901L
#define add_complex(a, b) ((a)+(b))
//similarly for other operations
#else //not C99
inline float_complex add_complex(float_complex a, float_complex b)
{
float_complex z = {a.re + b.re, a.im + b.im};
return z;
}
//similarly for subtract, multiply, divide, and comparison operations.
请注意add_complex(c, 5)
不C89模式在上面的代码工作,因为编译器不知道如何使5成一个复杂的。这是在C没有固定的编译器支持一个棘手的问题 - 你不得不求助于像新tgmath.h
用途,这是编译器特定的技巧
不幸的是,所有这一切的效果是,像a+b
漂亮C99语法添加复数已被写入add_complex(a, b)
。
另一种选择(如另一个海报所指向的)是使用C ++ std::complex
非C99编译器。这可能是确定的,如果你能在typedef和#ifdef
s换东西。然而,你需要无论是C ++或C99。
其他提示
有,是我在MSDN网站上找到一个图书馆。这里有一个链接。 http://msdn.microsoft.com/en-us/library/0352zzhd。 ASPX
我希望有所帮助。