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
しかし、私は、コンパイラが「フロート複合体」を認識できない場合は、これを行う方法を見て確認していません。私は実際には不可能だと思うだろうが、 Dinkumware にすることによってCライブラリは、そうでない場合を示しているようです。解決策は何ですか?私は種類の操作のための関数/マクロを使用して気にしないが、私は複素数に値を代入する方法が必要、とC99との互換性があるwhichi方法で、その実数/虚数部を取り戻すます。
ソリューション
私はこのような何かをやってしまいました
#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 <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.
コンパイラが複雑に5を作る方法を知らないためadd_complex(c, 5)
は、上記のコードではC89モードでは動作しないことに注意してください。これは、コンパイラのサポートなしでCに修正するトリッキーな問題である - 。あなたは、コンパイラ固有のもので、新たなtgmath.h
の用途のようなトリックに頼る必要があります。
残念ながら、このすべての効果は、複素数を追加するa+b
のような素敵なC99の構文はadd_complex(a, b)
を書かなければならないことである。
別のオプションは、(別のポスターが指摘したように)非C99のコンパイラでC ++ std::complex
を使用することです。あなたはtypedefのと#ifdef
sで物事をラップすることができます場合、これはOKかもしれません。ただし、C ++またはC99のいずれかが必要と思います。
他のヒント
私は、MSDNのWebサイト上で見つかったライブラリがあります。ここにリンクがあります。 http://msdn.microsoft.com/en-us/library/0352zzhd。 ASPXする
私はそれが役に立てば幸います。