Определение #if условия препроцессора в C - PullRequest
0 голосов
/ 14 января 2020

Я хотел определить проверку правильности ввода времени компиляции для библиотеки, которую я разрабатываю. Поэтому я подумал, что, может быть, #define функция типа #if препроцессора в C, которая будет скомпилирована с G CC, что-то связывает так:

#define VALIDITY_CHECK(x) {#if (x)>10
                              #error "input out of range"
                              #endif}

Но это не работает. Итак, как правильно написать такую ​​проверку правильности времени компиляции?

Ответы [ 2 ]

2 голосов
/ 14 января 2020

Вы можете использовать трюк, который вызывает ошибку времени компиляции, если условие не выполняется:

#define ASSERT(condition) (sizeof (struct { int:-!(condition); }))

#define x1 23
#define x2 42

void f(void) {
    ASSERT(x1 < 31);
    ASSERT(x1 > 31);
    ASSERT(x2 < 31);
    ASSERT(x2 > 31);
}

Он работает, оценивая условие оператором ! как 1 для false и 0 для true. Этот номер используется для объявления анонимного битового поля размером -1 или 0 соответственно в struct. Анонимная структура просто используется для оператора sizeof, а результат отбрасывается как неиспользуемое выражение.

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

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

Вы можете увеличить ASSERT() на комментарий за ним, если это необходимо. Диагностическое сообщение c покажет его.

    ASSERT(x1 < 31); // Bla bla bla
0 голосов
/ 14 января 2020

Вы не можете иметь макро-директивы со значением #define. Это связано с тем, что # в значении является оператором «stringizing», и за ним должен следовать макро-аргумент.

В значении #define вы можете иметь #x, поскольку x является аргументом VALIDITY_CHECK, но вы не можете иметь #if, #error или #endif .

Вы вынуждены везде явно писать следующий код.

#if (x)>10
#error "input out of range"
#endif
...