gpt4 book ai didi

C99 复杂支持与 visual studio

转载 作者:太空狗 更新时间:2023-10-29 17:24:03 25 4
gpt4 key购买 nike

我想使用 C99 中定义的复数,但我需要支持不支持它的编译器(想到 MS 编译器)。

我不需要很多功能,在没有支持的编译器上实现所需的功能也不是太困难。但是我很难实现“类型”本身。理想情况下,我想做类似的事情:

#ifndef HAVE_CREAL
double creal(complex z)
{
/* .... */
}
#endif

#ifndef HAVE_CREALF
float creal(float complex z)
{
/* ... */
}
#endif

但是如果编译器无法识别“浮点复数”,我不确定我该如何做到这一点。我实际上认为这是不可能的,但是 Dinkumware 的 C 库似乎另有说明。解决办法是什么 ?我不介意使用函数/宏来对类型进行操作,但我需要一种方法来为复数赋值,并以与 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 库函数,并且可以通过代码生成器部分自动化。

最佳答案

无论您做什么,都无法在非 C99 编译器中正确解析“float complex”。所以不要写那个,做一些typedefs。如果您只需要支持一种复杂类型,那就容易多了,所以我将仅使用 float complex 进行演示。

首先,定义类型:

#if __STDC_VERSION__ >= 199901L
//using a C99 compiler
#include &lt;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) 来添加复数。

另一种选择(如另一张海报所指)是在非 C99 编译器上使用 C++ std::complex。如果您可以将内容包装在 typedef 和 #ifdef 中,这可能没问题。但是,您需要 C++ 或 C99。

关于C99 复杂支持与 visual studio,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1063406/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com