#define 指令中的 sizeof 运算符
sizeof operator in #define directives
我一直在检查某人的代码,我遇到了这个:
#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)
是经过仔细编写的,因此编译器可以完全忽略该指令。
这是如何工作的?
sizeof
的操作数是未计算的,因此这确保了在 运行 时间没有要完成的工作。宏只是忽略了一个常量值;编译器可以看到它没有任何效果,因此不应从中生成任何代码。
与什么都不做相比的优势在于编译器仍然会检查参数是否为有效表达式;更改代码并仅为发布编译时,您不会意外破坏调试版本。
评论中提到的 (void)str
的优势在于,它会计算表达式,并且编译器可能无法消除它,因为它可能有副作用。例如:
extern std::string get_message(int code);
LOG_INFO(get_message(code)); // -> (void)get_message(code);
在发布版本中会调用该函数并忽略结果,从而影响性能。
我一直在检查某人的代码,我遇到了这个:
#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)
是经过仔细编写的,因此编译器可以完全忽略该指令。
这是如何工作的?
sizeof
的操作数是未计算的,因此这确保了在 运行 时间没有要完成的工作。宏只是忽略了一个常量值;编译器可以看到它没有任何效果,因此不应从中生成任何代码。
与什么都不做相比的优势在于编译器仍然会检查参数是否为有效表达式;更改代码并仅为发布编译时,您不会意外破坏调试版本。
评论中提到的 (void)str
的优势在于,它会计算表达式,并且编译器可能无法消除它,因为它可能有副作用。例如:
extern std::string get_message(int code);
LOG_INFO(get_message(code)); // -> (void)get_message(code);
在发布版本中会调用该函数并忽略结果,从而影响性能。