我不会依赖 gcc 编译器标志来做到这一点。编译器标志可以在 gcc 版本之间更改,并且在编译器之间进行更改。您可能会发现自己需要在六个月内使用 Visual C++ 调试相同的代码...
@CharlesBailey 对如何使用extern
变量提出了一个很好的建议。这是一种不需要将变量公开给整个模块或保存在静态存储中的替代方法。
volatile
在语句范围内声明一个临时变量if
:
if (volatile bool dbg = false)
{
do_some_debug_printing_and_checking();
}
这使临时变量的范围非常狭窄。volatile
限定符不会让编译器对变量进行任何假设,也不会优化分支。
要记住的一件事是变量总是在堆栈上分配,并且将一直保留在堆栈上,直到函数退出。这种方法和extern
方法都应该有效,但权衡取舍略有不同(并且可能可以忽略不计)。
如果您愿意使用宏来帮助解决此问题,那么您可以在将代码发布到生产环境时轻松禁用临时变量:
#ifndef IS_DEBUGGING
# define IS_DEBUGGING 0
#endif
#if IS_DEBUGGING
# define TMP_DBG_FLAG volatile bool dbg_flag = false
#else
# define TMP_DBG_FLAG false
#endif
然后将您的if
声明声明为:
if ( TMP_DBG_FLAG )
{
do_some_debug_printing_and_checking();
}
当您将 IS_DEBUGGING 定义为 1 时,将创建、声明为 volatile 并保留局部变量。当您将 IS_DEBUGGING 定义为 0 时,宏扩展为常量false
,编译器优化分支。也可以为该extern
方法做一些非常相似的事情。
这几行额外的代码,但它们与您使用 TMP_DBG_FLAG 的次数无关。该代码也比使用大量ifdef
s 更具可读性。可以使宏更安全一些(通过将值附加__LINE__
到它),但这需要三个宏,并且可能不是必需的:
#if IS_DEBUGGING
// paste symbols 'x' and 'y' together
# define TMP_DBG_FLAG_SYMCAT0(x,y) x ## y
// need one level of indirection to expand __LINE__...
# define TMP_DBG_FLAG_SYMCAT(x,y) TMP_DBG_FLAG_SYMCAT0(x,y)
# define TMP_DBG_FLAG volatile bool TMP_DBG_FLAG_SYMCAT(dbg_flag_,__LINE__) = false
#else
# define TMP_DBG_FLAG false
#endif