С++ void cast и операторская запятая в #define
Я нашел это при чтении некоторого исходного кода.
#define MACRO(x) if((void) 0, (x)); else some_func();
Я не совсем понимаю причины, стоящие за этой запятой оператора и литой пустоты. Вероятно, это связано с макрозащитой, я знаю, что (void)0
иногда используется для защиты каскадирования else
в макросах, например, в if(...) then foo(); else (void)0
.
Любые идеи о том, почему существует служебная запятая?
edit: Я начинаю думать, что это имеет какое-то отношение к owl (0,0)
.
Ответы
Ответ 1
Я бы предположил, что трюк используется для предотвращения объявления пользователем переменных в состоянии if
. Как вы, наверное, знаете, в С++ это законно сделать это
if (int i = some_func()) {
// you can use `i` here
}
else {
// and you can use `i` here
}
Использование оператора запятой в этом определении предотвратит использование макросов, например
MACRO(int i = some_func());
и заставить пользователя использовать только выражения в качестве аргумента.
Ответ 2
Преобразование void определенно предотвратит вызов перегруженного operator ,
, так как вы не можете перегрузить параметр void. Это гарантирует, что (void)0,
не имеет эффекта.
Зачем нужен оператор запятой? Хороший вопрос. Я действительно не знаю.
Ответ 3
Это немного похоже на то, что кто-то, возможно, начал с некоторого кода, который включал assert
, предварительно обработал его и превратил результат в макрос. Когда NDEBUG
определяется, assert
должен превратиться в почти ничего - но, синтаксически, все равно должен быть произведен некоторый код-заменитель. Например, вы можете использовать его в такой ситуации, как:
assert(x), *x = 1;
Когда вы компилируете это с помощью NDEBUG
, он все равно должен компилироваться, но assert
не должен ничего делать. Чтобы поддержать это, assert
обычно определяется примерно так:
#undef assert
#ifdef NDEBUG
#define assert(x) ((void)0)
#else
#define assert(x) ((!!x) || __failassert(x, __FILE__, __LINE__))
#endif
Итак, если кто-то начал с кода, как описано выше, а затем посмотрел на предварительно обработанную версию (с определением NDEBUG), они увидели бы что-то вроде:
((void *)0), *x = 1;
... и если они не очень хорошо понимают код, они могут подумать, что ((void)0)
действительно что-то означал/что-то сделал.