与Visual Studio的C99复杂的支持 [英] C99 complex support with visual studio

查看:273
本文介绍了与Visual Studio的C99复杂的支持的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用复数在C99定义的,但我需要支持不支持它的编译器(MS编译器浮现在脑海中)。

I would like to use complex numbers as defined in C99, but I need to support compilers which do not support it (MS compilers come to mind).

我不需要很多功能,并在编译器实现所需的功能,而不支持不是太困难。但我有一个很难实现类型本身。理想情况下,我想这样做:

I don't need many functions, and implementing the needed functions on compilers without support is not too difficult. But I have a hard time implementing the 'type' itself. Ideally, I would like to do something like:

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

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

但我不知道我看看如何做到这一点,如果编译器无法识别浮动情结。我真的认为这是不可能的,但C库通过的Dinkumware 似乎另有指示。解决办法是什么 ?我不介意使用函数/宏的类型的操作,但我需要一种方式来赋值给一个复数,并取回的方式whichi与C99兼容它的真正/虚部。

But I am not sure I see how to do this if the compiler cannot recognize 'float complex'. I would actually think it is impossible, but the C library by Dinkumware seems to indicate otherwise. What is the solution ? I don't mind using functions/macros for operations on the type, but I need a way to assign values to a complex number, and get back its real/imaginary part in a way whichi is compatible with 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

有类型定义,和如下定义的一组复杂的功能:

for the type definition, and as follows to define a set of complex functions:

#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目录的功能,它可以通过code发生器部分自动化。

That's a bit complicated, but this enables me to easily reuse C lib functions when available, and it can be partly automated through code generator.

推荐答案

不管你做什么,你不能让漂浮情结在非C99编译器正确解析。因此,而不是书面的,使一些类型定义。这是,如果你只需要支持一个复杂类型容易得多,所以我就用演示复杂的浮动

No matter what you do, you can't make "float complex" parse properly in a non-C99 compiler. So instead of writing that, make some typedefs. It's far easier if you only have to support one complex type, so I'll just demonstrate with 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。

Then, we need to be able to create complex numbers, and emulate creal and 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


接下来,编写包装加法,减法,乘法,除法和比较功能。

Next, write functions that wrap addition, subtraction, multiplication, division, and comparisons.


#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模式在上面code的工作,因为编译器不知道如何使5成一个复杂的。这是用C来解决,而不编译器支持一个棘手的问题 - 你不得不求助于像新的`tgmath.h`用途,这是编译器特定的技巧

Note that `add_complex(c, 5)` doesn't work in C89 mode in the above code, because the compiler doesn't know how to make 5 into a complex. This is a tricky problem to fix in C without compiler support -- you have to resort to tricks like the new `tgmath.h` uses, which are compiler-specific.


不幸的是,这一切的效果是,像'A + B`漂亮的C99语法添加复数已被写入`add_complex(A,B)`。

Unfortunately, the effect of all of this is that the nice C99 syntax like `a+b` to add complex numbers has to be written `add_complex(a, b)`.


另一种选择(如另一个海报指出)是用C ++'的std :: complex`非C99编译器。这可能是确定的,如果你能在typedef和`#ifdef`s换东西。但是,你需要或者C ++或C99。

Another option (as another poster pointed to) is to use C++ `std::complex` on non-C99 compilers. This might be OK if you can wrap things in typedefs and `#ifdef`s. However, you'd require either C++ or C99.

这篇关于与Visual Studio的C99复杂的支持的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆