Оператор 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);

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

Другие вопросы по тегам