Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C:while(0)时做{…}?_C_Macros - Fatal编程技术网

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,为什么<代码>无效*主赛道。