Я пытаюсь создать простой макрос утверждения, который возвращает логическое значение, но продолжает получать функцию void.
#define FALSE 0
#define TRUE !FALSE
#define CASSERT(predicate) \
({ \
if ((predicate)) \
{ \
(TRUE); \
}else\
{ \
__debugbreak(); \
(FALSE); \
}})
Я хочу использовать это вот так
if (!CASSERT(X==Y)){}
это ошибка, которую я получаю
error: void value not ignored as it ought to be
error: could not convert '<statement>' from 'void' to 'bool'
Я попробовал несколько вариантов этого кода, и ни один из них не работает! вывод CASSERT — это пустая функция!
В новом коде использования используйте stdbool.h вместо доморощенных логических значений. Есть ли причина, по которой вам нужны !TRUE
и !!FALSE
? Рассмотрите возможность инвертирования значения предиката или замены двух выражений условного оператора.
Если вы пытаетесь использовать выражения операторов GCC (gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html), то ваш синтаксис неверен - переменная с результирующим значением должна быть последней в блоке кода.
@qrdl Да, подтверждаю, в последнем блоке это тоже работает if (!(predicate)) { __debugbreak(); } (predicate);
Спасибо
@ ma1169 ma1169 Было бы лучше использовать локальную переменную в выражении оператора, чтобы параметр макроса predicate
расширялся только один раз. Например. #define CASSERT(predicate) ({ int result__ = (predicate) ? TRUE : FALSE; if (!result__) { __debugbreak(); } result__; })
.
Выполните замену текста самостоятельно.
if (!CASSERT(X==Y)){}
Становится:
if (!{
if ((X==Y)) {
(!0);
}
else {
__debugbreak();
(0);
}}) {}
Это похоже на действительный код C? Это не так, поскольку условный оператор не является выражением, возвращающим логическое значение.
Вы можете использовать условное выражение с оператором запятой для упорядочивания __debugbreak()
и FALSE
. Что-то вроде:
#define CASSERT(PRED) ((PRED) ? TRUE : (__debugbreak(), FALSE))
Теперь ваш код расширится до:
if (!((X==Y) ? !0 : (__debugbreak(), 1))) {}
Это действительный код C.
Я думаю, что оригинал на самом деле расширяется до if (!({
if ((X==Y))
{
{!0;
}
else {
__debugbreak();
0;
}}))
, в котором используется расширение GCC «выражение оператора» ({
… })
, где последний оператор в блоке может возвращать значение. Проблема в том, что выражение оператора исходного кода не содержит последнего оператора, возвращающего значение.
Вместо
{ if (predicate) ... else ...}
, может быть,(predicate) ? ... : ...
?