C нет оператора вне функций - PullRequest
0 голосов
/ 30 августа 2018

У меня есть код, содержащий много строк, таких как:

static_assert(sizeof(my_stuct)==42, "check struct size");

и я хочу скомпилировать компилятор, в котором не реализовано static_assert. Поэтому я хочу, чтобы эти строки стали неактивными. Я пробовал:

#define static_assert(COND, MSG) 

работает нормально, но я получаю предупреждение с помощью компилятора clang:

warning: extra ';' outside of a function [-Wextra-semi]

Существует ли простой неоперативный оператор C для внешних функций, который заканчивается точкой с запятой и который можно использовать повторно?

Ответы [ 4 ]

0 голосов
/ 30 августа 2018

Я хочу скомпилировать на компиляторе, в котором не реализован static_assert. Поэтому я хочу, чтобы эти строки стали неактивными.

Почему бы не объединить ответ Лундина (проверяя, имеет ли текущий компилятор реализованный или нет) с реализацией из static_assert (что не сложно сделать)?

Копирование реализации из PDCLib (что лицензировано CC0 ):

/* with dodgy implementations, you could also #ifndef static_assert */
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
#define _PDCLIB_cc( x, y )     x ## y
#define _PDCLIB_concat( x, y ) _PDCLIB_cc( x, y )

#define static_assert( e, m ) enum { _PDCLIB_concat( _PDCLIB_assert_, __LINE__ ) = 1 / ( !!(e) ) }
#endif

Для данного выражения e и сообщения m это объявляет анонимное перечисление с одним членом, имя которого _PDCLIB_assert_ объединяется с текущей строкой исходного файла (__LINE__) (так что вы можете иметь несколько static_assert() за исходный файл). Этот элемент имеет значение 1, деленное на 1, если выражение e является истинным, или делится на 0, если выражение ложное, что приводит к выводу, подобному этому, для ошибочного утверждения:

./path/to/source.c:57:94: warning: division by zero [-Wdiv-by-zero]
 #define static_assert( e, m ) enum { _PDCLIB_concat( _PDCLIB_assert_, __LINE__ ) = 1 / ( !!(e) ) }
                                                                                      ^

./path/to/header.h:571:1: note: in expansion of macro 'static_assert'
 static_assert( false, "test" );
 ^
./path/to/source.c:57:62: error: enumerator value for '_PDCLIB_assert_571' is not an integer constant
...

Это не красиво, но совершенно C89-совместимо, протестировано и обслуживаемо.

Не стесняйтесь переименовывать из _PDCLIB_* во все, что вы предпочитаете.

0 голосов
/ 30 августа 2018

Проверено только очень быстро, но как насчет:

#define static_assert(COND, MSG) extern int _no_static_assertion

или что? Повторять extern должно быть хорошо.

0 голосов
/ 30 августа 2018

Поскольку это функция C11, ответ довольно тривиален: просто проверьте, поддерживает ли компилятор C11.

#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112
  static_assert(sizeof(my_stuct)==42, "check struct size");
#endif 

И наоборот, чтобы сделать это бездействующим в отсутствие стандартного C и тем самым устранить необходимость в вышеуказанных переключателях компилятора повсюду, это:

#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
  #define static_assert(cond, str) struct dummy_t
#endif 

Хотя помните, что static_assert требует #include <assert.h>, в отличие от ключевого слова C11 _Static_assert.

0 голосов
/ 30 августа 2018

Мое решение до сих пор:

#define static_assert(COND, MSG) extern int __static_assert_dummy__

отлично работает, но мне кажется уродливым!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...