C:while(0)时做{…}?
可能的重复项:C:while(0)时做{…}?,c,macros,C,Macros,可能的重复项: 我正在编写一些C代码,其中包含如下宏: #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) 有人能解释一下这个宏是做什么的吗?为什么需要(0)?这不是只执行一次代码吗?执行while是一种常见的约定,它使得宏需要一个尾随分号,就像标准的c函数一样。除此之外,它只是确保已释放的变量设置为NULL,以便将来调用释放它时不会导致错误 do { stuff() } while(0); 正
我正在编写一些C代码,其中包含如下宏:
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
有人能解释一下这个宏是做什么的吗?为什么需要(0)?这不是只执行一次代码吗?执行while是一种常见的约定,它使得宏需要一个尾随分号,就像标准的c函数一样。除此之外,它只是确保已释放的变量设置为NULL,以便将来调用释放它时不会导致错误
do { stuff() } while(0);
正在做与stuff()完全相同的事情。那有什么大不了的?问题在于宏的语法。假设我们将宏定义为:
#define SAFE_FREE(x) if ((x) != NULL) { free(x); x=NULL; }
那么有两个问题。第一个相对较小:使用SAFE_FREE不再需要尾随分号。但更重要的是,代码如下:
if (...)
SAFE_FREE(x)
else
stuff();
if (today_is_tuesday())
SAFE_FREE(x);
else
eat_lunch();
将扩展到:
if (...)
if ((x) != NULL) {
free(x);
x = NULL;
} else
stuff();
如上所述定义宏可防止出现上述奇怪行为,因为
do{…}while(0)
的行为就像没有分号的语句。do/while(0)背后的思想是,可以在使用函数调用时使用宏,而不会出现意外错误
例如,如果您有如下代码:
if (...)
SAFE_FREE(x)
else
stuff();
if (today_is_tuesday())
SAFE_FREE(x);
else
eat_lunch();
宏只是:
#define SAFE_FREE(x) if (x) { free(x); x = 0; }
你会得到一个完全不同的结果。do/while约定通过使其行为一致来避免这些错误。顺便说一句,Bjarne Stroustrup建议使用内联(模板)函数来执行“删除并为空”
template inline void destroy(T*&p){delete p;p=0;}
此c代码在哪里使用?它是从哪里来的?重复:这个特定宏的一个问题是:SAFE\u FREE(get\u buffer())
之类的东西无法编译。创建这样的宏时要考虑的一些问题。如果((x)!=NULL)
是多余的。你可以安全地移除它<代码>免费(空)没有任何作用,那么为什么要浪费一个if
呢?@N1.1免费(空);是一种未定义的行为,仅仅因为所有现代操作系统都检查它并不意味着它是安全的。哇,现在你这样解释它,它是非常有意义的。太棒了。我以前见过do{}while(0)
位,但从未理解为什么。关于do/while(0)的要点是避免扩展代码,这与程序员的意图非常不同。@janm这可以通过使用大括号来实现,而不需要无用的do/while(0)。例如,<代码> >定义安全无(x){if((x)!=null){免费(x);x= null;}} /代码> @ Brandon Bodn Ar:不。考虑“if(test)安全无(x);否则BLAH());“即时语法错误。W.R.T”。“我不知道是否有像MSVC、gcc、icc、lcc等这样的人应该删除循环,但在编译代码时,优化无疑是一个很难解决的问题。“你甚至不需要特别好的编译器。这是一个非常常见的构造,即使关闭了优化,GCC也会对其进行优化。它本身甚至不是一种优化——可以让代码运行得更快:只是简单地消除不必要的语法。gcc不会在关闭优化的情况下对此进行优化。当优化关闭时,gcc不会做任何重构代码的事情,否则调试将是一场噩梦。@Jason Coo:嗯。。。是的。验证了一个包含和不包含“do{…}while(0);”包装器以及-O0和默认选项的简单示例。gcc给了我完全相同的输出。(4.3.2,Debian 4.3.2-1.1,关于Debian lenny。)为什么不只使用块呢?看起来do while(0)仍然是多余的,可以用一组大括号来完成,如上面的代码所示。分号是我能看到的唯一原因。@Jason调试怎么会变成噩梦?如果C有模板那就太好了:)@jmh lol,为什么<代码>无效*主赛道。