Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VisualStudio对C99的复杂支持_C_Visual Studio_C99_Complex Numbers - Fatal编程技术网

VisualStudio对C99的复杂支持

VisualStudio对C99的复杂支持,c,visual-studio,c99,complex-numbers,C,Visual Studio,C99,Complex Numbers,我想使用C99中定义的复数,但我需要支持不支持它的编译器(我想到了MS编译器) 我不需要很多函数,在没有支持的编译器上实现所需的函数也不太困难。但我很难实现“类型”本身。理想情况下,我想做如下工作: #ifndef HAVE_CREAL double creal(complex z) { /* .... */ } #endif #ifndef HAVE_CREALF float creal(float complex z) { /* ... */ } #endif 但是,如果编译器不能识别“

我想使用C99中定义的复数,但我需要支持不支持它的编译器(我想到了MS编译器)

我不需要很多函数,在没有支持的编译器上实现所需的函数也不太困难。但我很难实现“类型”本身。理想情况下,我想做如下工作:

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

#ifndef HAVE_CREALF
float creal(float complex z)
{
/* ... */
}
#endif
但是,如果编译器不能识别“float complex”,我不知道该怎么做。我实际上认为这是不可能的,但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

这有点复杂,但这使我能够在可用时轻松重用C库函数,并且可以通过代码生成器实现部分自动化。

我在msdn网站上找到了一个库。这里有一个链接。


我希望这能有所帮助。

无论您做什么,都无法在非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
用法之类的技巧,它们是特定于编译器的

不幸的是,所有这一切的效果是,像
a+b
这样用于添加复数的漂亮C99语法必须编写
add\u complex(a,b)


另一个选项(如另一个海报所指出的)是在非C99编译器上使用C++ <代码> STD::如果您可以用typedefs和

#ifdef
s来包装东西,这可能没问题。但是,您需要C++或C99。

C++没有用,因为在C链接的函数签名中,不能有STD::复合体。我可以在这个周围添加一个包装,但是,使用C++完全没有多大意义。因为项目现在不依赖C++,所以它代表了一个很大的依赖性——我需要支持很多平台,而不仅仅是最近的GCC和MS编译器。如果你担心你使用的链接风格,我想你需要在不同时间编译的对象文件之间有链接时间(二进制)兼容性。不仅仅是源代码兼容性。在这种情况下,最好始终使用struct float_复杂方法。否则,有人可能会在编译器的C89模式下编译一个文件,尝试调用C99模式下编译的库中的函数,并看到奇怪的结果,因为_Complex和float_Complex结构的调用约定不一样。我同意Doug的观点:如果你想要C99/C89兼容的代码,在FLUATH-Apple结构中,你不会使用+运算符,所以对两种类型,一个C99复合体,以及你内部复杂结构的兴趣不大。它是C++ <代码> <代码>标题。只要问题作者坚持使用C,他/她就不可能正确地使用它。
#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.