Подтвердить что ты не робот

Как переписать назначенные инициализаторы C-структуры на C89 (например, компилятор MSVC C)

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

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

//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 это работает нормально.
BUT cl не может скомпилировать это (из-за несчастной реализации C99): error C2059: syntax error : '.'

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


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

4b9b3361

Ответ 1

Несчастная реализация 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 *, либо прекратить инициализацию этих элементов строковыми литералами.

Ответ 2

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

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

Ответ 3

/*
 * 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)
};