سؤال

وأود أن استخدام الأعداد المركبة على النحو المحدد في C99، ولكني في حاجة لدعم المجمعين التي لا تدعم ذلك (المجمعين MS تتبادر إلى الذهن).

وأنا لست بحاجة إلى العديد من الوظائف، وتنفيذ المهام المطلوبة على المجمعين من دون دعم ليس من الصعب جدا. ولكن لدي صعوبة في تنفيذ 'نوع' نفسها. من الناحية المثالية، أود أن تفعل شيئا مثل:

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

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

ولكن لست متأكدا أرى كيفية القيام بذلك إذا كان المترجم لا يمكن التعرف على "مجمع تعويم". وأود أن أعتقد فعلا أنه من المستحيل، ولكن المكتبة C بواسطة Dinkumware يبدو أنها تشير إلى خلاف ذلك. ماهو الحل ؟ أنا لا أمانع باستخدام وظائف / وحدات الماكرو لعمليات على نوع، ولكن أنا بحاجة إلى وسيلة لتعيين قيم لعدد معقدة، ونعود جانبها الحقيقي / وهمي بطريقة whichi متوافق مع 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 عندما تكون متاحة، وأنه يمكن أن يكون آليا جزئيا من خلال مولد رمز.

هل كانت مفيدة؟

المحلول

وبغض النظر عن ما تفعله، وأنت لا يمكن أن تجعل "تعويم معقدة" تحليل صحيح في مترجم غير C99. وذلك بدلا من كتابة ذلك، وجعل بعض typedefs. انه من الاسهل بكثير إذا كان لديك فقط لدعم نوع واحد معقدة، ولذا فإنني سوف تثبت فقط مع 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).

وثمة خيار آخر (كما أشار ملصق آخر ل) هو استخدام std::complex C ++ على المجمعين غير C99. وهذا قد يكون موافق إذا يمكنك لف الأشياء في typedefs و#ifdefs. ومع ذلك، وكنت تتطلب إما C ++ أو C99.

نصائح أخرى

وهناك المكتبة التي وجدت على موقع MSDN. وإليك وصلة. http://msdn.microsoft.com/en-us/library/0352zzhd. ASPX

وآمل أن يساعد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top