Макросы, такие как ((int)0)
или ((void)0)
, вероятно, являются наиболее гибкими и безопасными неоперационными макросами. Они гибки, потому что вы можете использовать их
в выражениях (в отличие от do{}while(0)
), и они не ломаются if-else
, как {}
или ;
.
Пример того, как макросы {}
(или ;
) ломаются if
- else
:
#define foo() {}
if(1) foo(); else bar(); //syntax error because if(1) {}; else bar(); was pasted
Если макрос должен эмулировать целочисленную возвращаемую функцию, лучше использовать приведенный целочисленный литерал над простой целочисленной константой, поскольку целочисленные константы (и особенно нули) могут использоваться в большем количестве контекстов (метки падежа, размеры битового поля, размеры массива, ноль) константы указателя), чем неконстантные целочисленные выражения.
Вам не нужно иметь два макроса, как в:
#if HAVE_LIBFOOBAR
#define foobar_func_if_available(x) foobar_func(x)
#else
#define foobar_func_if_available(x) ((void)0) /*if foobar_func returns void*/
#endif
Вы можете поместить условие в макрос:
#define foobar_func_if_available(x) \
(HAVE_LIBFOOBAR?foobar_func(x):((void)0))
Даже очень тупой компилятор должен уметь оптимизировать константу условного вывода.
Но если вы полагаетесь на пустое значение HAVE_LIBFOOBAR
, равное 0
внутри #if
, то вышеприведенное не сработает - HAVE_LIBFOOBAR должен быть целым числом.
(
Вы могли бы сделать
#if !HAVE_LIBFOOBAR
#undef HAVE_LIBFOOBAR
#define HAVE_LIBFOOBAR 0
#endif
#define foobar_func_if_available(x) \
(HAVE_LIBFOOBAR?foobar_func(x):((void)0))
для нормализации пустого HAVE_LIBFOOBAR
в 0
, но если вы не будете повторно использовать определенную теперь гарантированную HAVE_LIBFOOBAR
, это кажется ненужным осложнением по сравнению с исходными двумя макросами foobar_func_if_available
.
)