Jon*_*age 109 c c++ if-statement coding-style c-preprocessor
这可能是一种风格问题,但我们的开发团队有一点分歧,我想知道是否有其他人对此事有任何想法......
基本上,我们有一些调试打印语句,我们在正常开发过程中关闭.我个人更喜欢做以下事情:
//---- SomeSourceFile.cpp ----
#define DEBUG_ENABLED (0)
...
SomeFunction()
{
int someVariable = 5;
#if(DEBUG_ENABLED)
printf("Debugging: someVariable == %d", someVariable);
#endif
}
Run Code Online (Sandbox Code Playgroud)
有些团队更喜欢以下内容:
// #define DEBUG_ENABLED
...
SomeFunction()
{
int someVariable = 5;
#ifdef DEBUG_ENABLED
printf("Debugging: someVariable == %d", someVariable);
#endif
}
Run Code Online (Sandbox Code Playgroud)
......哪些方法对你来说听起来更好?为什么?我的感觉是,第一个更安全,因为总有一些东西被定义,并且没有危险它可以破坏其他地方的其他定义.
Rod*_*ddy 80
#ifdef
当然,我最初的反应是,但我认为#if
实际上有一些显着的优势 - 这就是为什么:
首先,您可以DEBUG_ENABLED
在预处理器和编译测试中使用.示例 - 通常,在启用调试时我想要更长的超时,所以使用#if
,我可以写这个
DoSomethingSlowWithTimeout(DEBUG_ENABLED? 5000 : 1000);
Run Code Online (Sandbox Code Playgroud)
... 代替 ...
#ifdef DEBUG_MODE
DoSomethingSlowWithTimeout(5000);
#else
DoSomethingSlowWithTimeout(1000);
#endif
Run Code Online (Sandbox Code Playgroud)
其次,如果要从a迁移#define
到全局常量,则处于更好的位置.#define
大多数C++程序员通常都不赞同.
而且,第三,你说你的团队存在分歧.我的猜测是,这意味着不同的成员已采用不同的方法,您需要标准化.裁决#if
是首选的选择意味着代码使用#ifdef
将编译 - 并运行 - 即使DEBUG_ENABLED
是假的.而且它的很多容易追查并卸下时,它不应该比反之亦然生产调试输出.
哦,还有一个小的可读性点.你应该能够使用真/假而不是0/1 #define
,并且因为该值是单个词法标记,所以有一次你不需要围绕它的括号.
#define DEBUG_ENABLED true
Run Code Online (Sandbox Code Playgroud)
代替
#define DEBUG_ENABLED (1)
Run Code Online (Sandbox Code Playgroud)
R..*_*R.. 55
他们都很可怕.相反,这样做:
#ifdef DEBUG
#define D(x) do { x } while(0)
#else
#define D(x) do { } while(0)
#endif
Run Code Online (Sandbox Code Playgroud)
然后,只要您需要调试代码,请将其放入D();
.并且您的程序没有被可怕的迷宫污染#ifdef
.
Ter*_*son 29
#ifdef
只是检查是否定义了一个令牌
#define FOO 0
Run Code Online (Sandbox Code Playgroud)
然后
#ifdef FOO // is true
#if FOO // is false, because it evaluates to "#if 0"
Run Code Online (Sandbox Code Playgroud)
Bre*_*ddy 18
我们在多个文件中遇到了同样的问题,并且总是存在人们忘记包含"功能标志"文件的问题(代码库> 41,000个文件很容易做到).
如果你有feature.h:
#ifndef FEATURE_H
#define FEATURE_H
// turn on cool new feature
#define COOL_FEATURE 1
#endif // FEATURE_H
Run Code Online (Sandbox Code Playgroud)
但是你忘了在header.cpp中包含头文件:
#if COOL_FEATURE
// definitely awesome stuff here...
#endif
Run Code Online (Sandbox Code Playgroud)
然后你有一个问题,在这种情况下,编译器将COOL_FEATURE解释为未定义为"false",并且无法包含代码.是的,gcc确实支持一个导致未定义宏错误的标志......但是大多数第三方代码要么定义要素,要么不定义要素,所以这不是那么便携.
我们采用了一种便携式方法来纠正这种情况,并测试一个功能的状态:功能宏.
如果您将上述feature.h更改为:
#ifndef FEATURE_H
#define FEATURE_H
// turn on cool new feature
#define COOL_FEATURE() 1
#endif // FEATURE_H
Run Code Online (Sandbox Code Playgroud)
但是你再次忘记在file.cpp中包含头文件:
#if COOL_FEATURE()
// definitely awseome stuff here...
#endif
Run Code Online (Sandbox Code Playgroud)
由于使用了未定义的函数宏,预处理器会出错.
Mik*_*son 16
出于执行条件编译的目的,#if和#ifdef 几乎相同,但并不完全相同.如果条件编译依赖于两个符号,则#ifdef也不会起作用.例如,假设您有两个条件编译符号PRO_VERSION和TRIAL_VERSION,您可能会遇到以下情况:
#if defined(PRO_VERSION) && !defined(TRIAL_VERSION)
...
#else
...
#endif
Run Code Online (Sandbox Code Playgroud)
使用#ifdef变得更加复杂,特别是让#else部分工作.
我在广泛使用条件编译的代码上工作,我们混合了#if和#ifdef.对于简单情况,我们倾向于使用#ifdef /#ifndef;对于正在评估的两个或更多符号,我们倾向于使用#if.
我自己更喜欢:
#if defined(DEBUG_ENABLED)
Run Code Online (Sandbox Code Playgroud)
因为它更容易创建代码来查找相反的条件更容易发现:
#if !defined(DEBUG_ENABLED)
Run Code Online (Sandbox Code Playgroud)
与
#ifndef(DEBUG_ENABLED)
Run Code Online (Sandbox Code Playgroud)
这是一种风格问题.但我建议采用更简洁的方法:
#ifdef USE_DEBUG
#define debug_print printf
#else
#define debug_print
#endif
debug_print("i=%d\n", i);
Run Code Online (Sandbox Code Playgroud)
你这样做一次,然后总是使用debug_print()打印或什么都不做.(是的,这将在两种情况下编译.)这样,您的代码不会被预处理器指令乱码.
如果你收到警告"表达没有效果"并想要摆脱它,这里有一个替代方案:
void dummy(const char*, ...)
{}
#ifdef USE_DEBUG
#define debug_print printf
#else
#define debug_print dummy
#endif
debug_print("i=%d\n", i);
Run Code Online (Sandbox Code Playgroud)