Статичный утверждают в C

То, что лучший способ состоит в том, чтобы достигнуть статичного времени компиляции, утверждает в C (не C++) с особым акцентом на GCC?

78
задан Matt Joiner 2 August 2010 в 06:32
поделиться

2 ответа

Из Википедии :

#define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;}

COMPILE_TIME_ASSERT( BOOLEAN CONDITION );
4
ответ дан 24 November 2019 в 10:29
поделиться

Это работает в функциональной и нефункциональной области видимости (но не внутри структур, объединений).

#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1]

STATIC_ASSERT(1,this_should_be_true); 

int main()
{
 STATIC_ASSERT(1,this_should_be_true); 
}
  1. Если утверждение времени компиляции не может быть сопоставлено, то GCC sas.c: 4: error: размер массива static_assertion_this_should_be_true создает почти понятное сообщение.

  2. Макрос может или должен быть изменено, чтобы сгенерировать уникальное имя для typedef (например, объединить __ LINE __ в конце static_assert _... name)

  3. Вместо тернарного можно также использовать #define STATIC_ASSERT (COND, MSG) typedef char static_assertion _ ## MSG [2 * (!! (COND)) - 1] , который работает даже на устаревшем компиляторе olde cc65 (для 6502 cpu) .

ОБНОВЛЕНИЕ: Для полноты картины, вот версия с __ LINE __

#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(!!(COND))*2-1]
// token pasting madness:
#define COMPILE_TIME_ASSERT3(X,L) STATIC_ASSERT(X,static_assertion_at_line_##L)
#define COMPILE_TIME_ASSERT2(X,L) COMPILE_TIME_ASSERT3(X,L)
#define COMPILE_TIME_ASSERT(X)    COMPILE_TIME_ASSERT2(X,__LINE__)

COMPILE_TIME_ASSERT(sizeof(long)==8); 
int main()
{
    COMPILE_TIME_ASSERT(sizeof(int)==4); 
}

UPDATE2: специальный код GCC

GCC 4.3 (я полагаю) представил атрибуты функций «error» и «warning». Если вызов функции с этим атрибутом не может быть устранен с помощью удаления мертвого кода (или других мер), генерируется ошибка или предупреждение. Это можно использовать для создания утверждений времени компиляции с пользовательскими описаниями ошибок. Осталось определить, как их можно использовать в области пространства имен, не прибегая к фиктивной функции:

#define CTC(X) ({ extern int __attribute__((error("assertion failure: '" #X "' not true"))) compile_time_check(); ((X)?0:compile_time_check()),0; })

// never to be called.    
static void my_constraints()
{
CTC(sizeof(long)==8); 
CTC(sizeof(int)==4); 
}

int main()
{
}

И вот как это выглядит:

$ gcc-mp-4.5 -m32 sas.c 
sas.c: In function 'myc':
sas.c:7:1: error: call to 'compile_time_check' declared with attribute error: assertion failure: `sizeof(int)==4` not true
83
ответ дан 24 November 2019 в 10:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: