How to rewrite C-struct designated initializers to C89 (resp MSVC C compiler)

故事扮演 提交于 2019-11-30 17:42:32

Miserable C99 implementation? I don't think that C compiler in VC2008 even tries to implement C99. It might borrow some features, but it is really a C89/90 compiler.

Just drop the field name tags

static struct my_member_t my_global_three[] = {
    { NULL, "one"},
    { NULL, "two"},
    { NULL, "three"},
};

In this case it is easy, since the order of the initializers in the original code is the same as the order of fields in the struct. If the order was different, you'd have to rearrange them in the tagless C89/90 version.

And if it's really your my_member_t, then you should either declare the string pointer as const char * or stop initializing these members with string literals.

cordic

Thanks for your information, Nico.

However, I have found out that for structs with arrays inside do not work. I propose this modification that works for both in C99 and MSVC (verified in MSVC++2010 Express):

#ifdef HAVE_DESIGNATED_INITIALIZERS
#define SFINIT(f, ...) f = __VA_ARGS__
#else
#define SFINIT(f, ...) __VA_ARGS__
#endif

typedef struct {
  int val;
  int vecB[4];
  int vecA[4];
} MyStruct_ts;

static const MyStruct_ts SampleStruct =
{
    SFINIT(.val     , 8),
    SFINIT(.vecB    , { 1, -2,  4,  -2}),
    SFINIT(.vecA    , { 1, -3,  5,  -3}),
};

This way you can use one single file for MSVC and other compilers.

/*
 * Macro for C99 designated initializer -> C89/90 non-designated initializer
 *
 * Tested.  Works with MSVC if you undefine HAVE_DESIGNATED_INITIALIZERS.  Cscope also
 * groks this.
 *
 * ("SFINIT" == struct field init, but really, it can be used for array initializers too.)
 */
#ifdef HAVE_DESIGNATED_INITIALIZERS
#define SFINIT(f, v) f = v
#else
#define SFINIT(f, v) v
#endif

struct t {
    char f1;
    int f2;
    double f3;
};

struct t t = {
    SFINIT(.f1, 'a'),
    SFINIT(.f2, 42),
    SFINIT(.f3, 8.13)
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!