C99 Visual Studio와의 복잡한 지원
-
21-08-2019 - |
문제
C99에 정의 된대로 복소수를 사용하고 싶지만 지원하지 않는 컴파일러를 지원해야합니다 (MS 컴파일러가 떠 오릅니다).
많은 기능이 필요하지 않으며 지원없이 컴파일러에서 필요한 기능을 구현하는 것은 그리 어렵지 않습니다. 그러나 나는 '유형'자체를 구현하는 데 어려움을 겪고 있습니다. 이상적으로는 다음과 같은 일을하고 싶습니다.
#ifndef HAVE_CREAL
double creal(complex z)
{
/* .... */
}
#endif
#ifndef HAVE_CREALF
float creal(float complex z)
{
/* ... */
}
#endif
그러나 컴파일러가 'float complex'를 인식 할 수 없다면이 작업을 수행하는 방법을 잘 모르겠습니다. 나는 실제로 그것이 불가능하다고 생각하지만 C 라이브러리는 Dinkumware 다른 것을 나타내는 것 같습니다. 해결책은 무엇인가 ? 유형의 작업에 Functions/Macros를 사용하는 것은 마음에 들지 않지만 값을 복소수로 할당하고 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가 아닌 컴파일러에서 "플로트 콤플렉스"를 제대로 만들 수 없습니다. 따라서 글을 쓰지 않고 일부 타이핑을 만드십시오. 하나의 복잡한 유형 만 지원해야한다면 훨씬 쉽습니다. 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)
컴파일러는 5를 복합체로 만드는 방법을 모르기 때문에 위 코드에서 C89 모드에서 작동하지 않습니다. 이것은 컴파일러 지원없이 C에서 해결하기가 까다로운 문제입니다. 새로운 것과 같은 트릭에 의지해야합니다. tgmath.h
컴파일러-특이 적 인 용도.
불행히도,이 모든 것의 효과는 멋진 C99 구문이 a+b
복소수를 추가하려면 작성해야합니다 add_complex(a, b)
.
또 다른 옵션 (다른 포스터가 지적한 것처럼)은 C ++를 사용하는 것입니다. std::complex
비 C99 컴파일러에서. typedefs로 물건을 감을 수 있다면 괜찮을 것입니다. #ifdef
에스. 그러나 C ++ 또는 C99가 필요합니다.
다른 팁
MSDN 웹 사이트에서 찾은 도서관이 있습니다. 여기 링크가 있습니다.http://msdn.microsoft.com/en-us/library/0352zzhd.aspx
도움이되기를 바랍니다.