Оператор sizeof в директивах #define
Я проверял чей-то код и столкнулся с этим:
#else //If not in Debug mode
#define LOG_WARNING(str) do { (void)sizeof(str); } while(0)
#define LOG_INFO(str) do { (void)sizeof(str); } while(0)
// ... More #define directives
#endif
По-видимому, do { (void)sizeof(str); } while(0)
тщательно написана, поэтому компилятор может полностью игнорировать директиву.
Как это работает?
1 ответ
Операнд sizeof
является неоцененным, так что это гарантирует, что во время выполнения не будет выполнено никакой работы. Макрос просто игнорирует постоянное значение; компилятор может видеть, что это не имеет никакого эффекта, поэтому не должен генерировать из него код.
Преимущество бездействия в том, что компилятор все еще проверяет, что аргумент является допустимым выражением; вы случайно не нарушите отладочную сборку при изменении кода и только при компиляции для выпуска.
Преимущество над (void)str
Упоминается в комментариях, что это будет оценивать выражение, и компилятор может не быть в состоянии устранить его, так как могут возникнуть побочные эффекты. Например:
extern std::string get_message(int code);
LOG_INFO(get_message(code)); // -> (void)get_message(code);
в сборке релиза вызывается функция и игнорируется результат, влияющий на производительность.