Оказалось, что статические утверждения без проблем реализуются и в си, причем несколькими способами.
Способ первый:
#define STATIC_ASSERT(exp) extern char __static_assert[(exp) ? 1 : -1]
Этот весьма универсальный способ можно использовать непосредственно за описанием структуры.
strict foo {...};
STATIC_ASSERT (sizeof (struct foo) == xxx);
Попытка объявить массив отрицательного размера вызывает массу ругани.
Встречаются и менее универсальные способы - например:
#define STATIC_ASSERT(exp) switch (0) { case 0: case ((exp) ? 1 : 0): break; }
Но такие ассерты ограничены в области применения. Их нельзя будет использовать за пределами функций. Думаю что так же не стоит пытаться оборачивать первый вариант традиционным для макросов
do { } while (0)
, Это так же сократит возможности его использования.Про статические утверждения все. Но есть еще кое что, что хотел бы рассказать.
Для большей наглядности вместо соответствующего стандарту си - assert(exp) создал STUB_ASSERT(exp, msg), который в случае нарушения ругается не просто выражениями, а целыми предложениями. Заодно можно держаться в ядре немного подальше от стандарта, чтобы не конфликтовать с ним.
Ну сделать с сообщением не проблема, проблема в том, как сделать так, чтобы в местах использования старой формы появлялись варнинги, не нарушающие сборку программы. Можно сказать мягкая форма устаревания макросов. И выход нашелся.
#define assert(exp) STUB_ASSERT((exp) && 'FOOF', #exp)
Выражение
'FOOF'
является допустимой для gcc многосимвольной константой, на которую выдается предупреждение 'Page.c:44:38: warning: multi-character character constant'. Можно конечно побаловаться с другими вариантами предупреждающих выражений, но в любом случае большой наглядности на этапе компиляции добиться не получится. Предупреждение и без того весьма примечательное.
0 коммент.:
Отправить комментарий