簡體   English   中英

Visual Studio支持C99綜合

[英]C99 complex support with visual studio

我想使用C99中定義的復數,但是我需要支持不支持它的編譯器(我想到了MS編譯器)。

我不需要很多功能,並且在沒有支持的情況下在編譯器上實現所需的功能也不太困難。 但是我很難實現“類型”本身。 理想情況下,我想執行以下操作:

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

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

但是我不確定如果編譯器無法識別“ float complex”,該如何執行。 我實際上認為這是不可能的,但是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函數(如果可用),並且可以通過代碼生成器部分自動化。

無論您做什么,都無法在非C99編譯器中正確進行“浮點復雜”解析。 因此,與其編寫,不如編寫一些typedef。 如果您只需要支持一種復雜類型,這要容易得多,所以我將僅以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用法之類的技巧,這些技巧是特定於編譯器的。

不幸的是,所有這些的結果是必須將漂亮的C99語法(如a+b加成復數,必須寫成add_complex(a, b)

另一個選擇(正如另一位發布者所指出的)是在非C99編譯器上使用C ++ std::complex 如果可以將內容包裝在typedefs和#ifdef則可能可以。 但是,您將需要C ++或C99。

我在msdn網站上找到了一個庫。 這是一個鏈接。 http://msdn.microsoft.com/zh-CN/library/0352zzhd.aspx

希望對您有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM