Как переписать C-struct назначенные инициализаторы в C89 (или компилятор MSVC C) - PullRequest
14 голосов
/ 26 марта 2011

ребята, у меня есть эта проблема:

Обычно в C99 GCC (cygwin / MinGW / linux), есть синтаксис с точечной нотацией для инициализаторов в структуре C.
Например:

//HELP ME HOW TO REWRITE THIS (in most compact way) to MSVC
static struct my_member_t my_global_three[] = {
    {.type = NULL, .name = "one"},
    {.type = NULL, .name = "two"},
    {.type = NULL, .name = "three"},
};

Имея my_memeber_t, определенную в заголовочном файле как:

struct my_member_t {
    struct complex_type * type;
    char * name;
    int default_number;
    void * opaque;
};

Я компилирую код Linux в MSVC 9.0 (Visual Studio 2008), наCygwin / MinGW это работает нормально.
НО cl не может скомпилировать это (из-за жалкой реализации C99): error C2059: syntax error : '.'

PROBLEM:<br> How to rewrite (many) global structs in a way that MSVC(resp C89)can compile it?


С уважением и благодарностью за предложения ...

Ответы [ 3 ]

17 голосов
/ 26 марта 2011

Ужасная реализация C99? Я не думаю, что компилятор C в VC2008 даже пытается реализовать C99. Это может заимствовать некоторые функции, но это действительно компилятор C89 / 90.

Просто бросьте теги имен полей

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

В этом случае это просто, поскольку порядок инициализаторов в исходном коде совпадает с порядком полей в структуре. Если бы порядок был другим, вам пришлось бы переставить их в версии без метки C89 / 90.

И если это действительно ваш my_member_t, то вы должны либо объявить строковый указатель как const char *, либо прекратить инициализацию этих членов строковыми литералами.

3 голосов
/ 15 ноября 2012

Спасибо за вашу информацию, Нико.

Однако я обнаружил, что для структур с массивами внутри не работают.Я предлагаю эту модификацию, которая работает как в C99, так и в MSVC (проверено в 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}),
};

Таким образом, вы можете использовать один единственный файл для MSVC и других компиляторов.

1 голос
/ 30 января 2012
/*
 * 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)
};
...