Visual Studio 的 C99 复杂支持

发布于 2024-07-25 08:53:27 字数 1582 浏览 3 评论 0原文

我想使用 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 lib 函数,并且可以通过以下方式部分自动化:代码生成器。

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

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.

Solution

I ended up doing something like this:

#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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心奴独伤 2024-08-01 08:53:27

无论您做什么,都无法在非 C99 编译器中正确解析“浮点数复杂”。 因此,不要编写这些内容,而是创建一些 typedef。 如果您只需要支持一种复杂类型,那就容易得多,因此我将仅使用 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 使用之类的技巧,这些技巧是特定于编译器的。

不幸的是,所有这些的结果是必须编写 add_complex(a, b) 等用于添加复数的 C99 语法(例如 a+b)。

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

First, define the types:

#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

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.

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.

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).

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 #ifdefs. However, you'd require either C++ or C99.

北城挽邺 2024-08-01 08:53:27

我在 msdn 网站上找到了一个库。 这是一个链接。
http://msdn.microsoft.com/en-us/library/0352zzhd。 aspx

我希望有帮助。

There is a library that I found on the msdn website. Here's a link.
http://msdn.microsoft.com/en-us/library/0352zzhd.aspx

I hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文