Необязательный инициализатор с помощью обмана препроцессора?

Я знаю, что это не сработает, но, надеюсь, вы видите, что я пытаюсь сделать.

#if ASSIGN_ALLOWED
    #define MAYBE_SKIP_REST_OF_LINE 
#else
    #define MAYBE_SKIP_REST_OF_LINE ; //
#endif

char str[80]  MAYBE_SKIP_REST_OF_LINE = "Hello\n";
long array[3] MAYBE_SKIP_REST_OF_LINE = { 7,8,9 };
int x         MAYBE_SKIP_REST_OF_LINE = 3;
//...many many more similar lines...

Есть ли способ сделать это так, чтобы он работал?


person Mick    schedule 30.09.2009    source источник
comment
Какие проблемы вы хотели бы решить с помощью этого трюка?   -  person sambowry    schedule 30.09.2009
comment
Извините, слишком сложно объяснить. Но это часть ужасного взлома очень большой, очень старой программы. Я не предлагаю никому копировать меня.   -  person Mick    schedule 30.09.2009


Ответы (4)


Конечно:

#ifdef ASSIGN_ALLOWED
    #define OPTIONAL_INITIALISER(x) = x 
#else
    #define OPTIONAL_INITIALISER(x) 
#endif

char str[80] OPTIONAL_INTIALISER("Hello\n");
#define ARRAY_INIT { 7,8,9 }
long array[3] OPTIONAL_INITIALISER(ARRAY_INIT);
#undef ARRAY_INIT
int x OPTIONAL_INITIALISER(3);

Любые инициализаторы, содержащие запятые, например array в примере, должны быть расширены из их собственного макроса, например ARRAY_INIT в приведенном выше примере. Если ваш компилятор поддерживает макросы C99 varargs, вы можете вместо этого сделать это более чистым способом:

#ifdef ASSIGN_ALLOWED
    #define OPTIONAL_INITIALISER(...) = __VA_ARGS__ 
#else
    #define OPTIONAL_INITIALISER(...) 
#endif

char str[80] OPTIONAL_INTIALISER("Hello\n");
long array[3] OPTIONAL_INITIALISER({ 7,8,9 });
int x OPTIONAL_INITIALISER(3);
person caf    schedule 30.09.2009
comment
разве запятые в 7,8,9 не заставят препроцессор думать, что макрос получил три аргумента? - person Mick; 30.09.2009
comment
Мик: Ах, да, переделал, чтобы исправить это. - person caf; 30.09.2009
comment
VA_ARGS теперь лучше. - person Mick; 30.09.2009
comment
еще одно предложение: добавьте фигурные скобки в определение макроса, т.е. = { __VA_ARGS__ } ; это работает и для скалярных типов: int foo = { 4 }; допустим C - person Christoph; 30.09.2009

Поскольку комментарии отфильтровываются при запуске препроцессора, я так не думаю.

person psychoschlumpf    schedule 30.09.2009

Это зависело бы от того, как препроцессор работал с комментариями и макросами. Если он удаляет комментарии после раскрытия макроса, то у вас все гладко, но в противном случае он может не работать просто из-за реализации препроцессора.

Вы могли бы попробовать это? (хотя это было бы грязно).

#define MAYBE_SKIP(code) code
#define MAYBE_SKIP(code) /* code */
person Nick Bedford    schedule 30.09.2009
comment
Комментарии удаляются слишком рано, чтобы это сработало. Возможно, вам следует проверить, прежде чем предлагать ответы; это позволит избежать отрицательных голосов. (Нет, это был не мой.) - person Jonathan Leffler; 30.09.2009

Препроцессор удаляет закомментированные разделы. Попробуйте запустить

gcc -E source.c

Это запустит препроцессор вашего кода, но фактически не скомпилирует его, что позволит вам увидеть, что произойдет после раскрытия макроса. Вы должны заметить, что все комментарии исчезли из любых развернутых макросов.

person Artelius    schedule 30.09.2009
comment
Точное наблюдение - но не предложение, как достичь желаемого результата. - person Jonathan Leffler; 30.09.2009