当前位置:  开发笔记 > 编程语言 > 正文

做{...}而(0) - 有什么好处?

如何解决《做{}而(0)-有什么好处?》经验,为你挑选了4个好方法。

它是C中唯一可用于#defineif语句操作的结构,后面加一个分号,并且仍然在语句中使用.一个例子可能有帮助:

#define FOO(x) foo(x); bar(x)

if (condition)
    FOO(x);
else // syntax error here
    ...;

即使使用大括号也无济于事:

#define FOO(x) { foo(x); bar(x); }

if语句中使用它将要求您省略分号,这是违反直觉的:

if (condition)
    FOO(x)
else
    ...

如果你这样定义FOO:

#define FOO(x) do { foo(x); bar(x); } while (0)

那么以下语法是正确的:

if (condition)
    FOO(x);
else
    ....

@LarryF:问题是,如果您正在编写供其他人使用的头文件,则无法选择其他人如何使用您的宏.为了避免对用户造成意外的意外,您必须使用上述技术使您的宏行为与任何其他C语句的行为一样. (45认同)

如果编码正确的话,我仍然认为这是UGLY和SLOPPY编码,并且可以避免.这可以追溯到一些常识C规则,总是在你的IF语句中使用卷曲,即使在IF之后只有一个操作.这应该是标准做法,IMVHO ...... (13认同)

不会`#define FOO(x)if(true){foo(x); 杆(X); } else void(0)`即使它更丑陋也可以工作? (5认同)

@ user10607:是的,如果你的宏扩展是*表达式*的列表,那么这是有效的.但是,如果你想在扩展中包含一个`if`或`while`,那么这个技巧也行不通. (4认同)

但是`#define FOO(x)foo(x),bar(x)`如何使用逗号代替分号.如果不这样做,这不会很好吗? (2认同)

这个答案多么令人惊讶 (2认同)

@Max好的,如果您仍然对自己的问题有疑问,请提出新问题,而不是使用评论.谢谢. (2认同)


Jere.Jones.. 105

这是一种简化错误检查并避免深层嵌套if的方法.例如:

do {
  // do something
  if (error) {
    break;
  }
  // do something else
  if (error) {
    break;
  }
  // etc..
} while (0);

或者使用`goto`.不,严重的说,`if(错误)转到错误;`和一个`错误:......`接近结尾似乎是一个更清洁的版本,对我来说完成同样的事情. (63认同)

呃,将其纳入方法,并使用早期回报. (14认同)

或者......只需使用do {} while(0). (13认同)

@WChargin:您链接的文章中的"goto fail"代码也会因"中断"而失败.有人刚刚在那里复制了一条线.这不是goto的错. (5认同)

@NiccoloM."被授予,goto不是错误,这实际上让它更有趣" (4认同)


Martin v. Lö.. 76

它有助于将多个语句分组到一个语句中,因此类似函数的宏实际上可以用作函数.假设你有

#define FOO(n)   foo(n);bar(n)

你也是

void foobar(int n) {
  if (n)
     FOO(n);
}

然后这扩大到

void foobar(int n) {
  if (n)
     foo(n);bar(n);
}

请注意,第二个调用(bar(n))不再是if语句的一部分.

将两者都包装到do {} while(0)中,也可以在if语句中使用宏.



1> Greg Hewgill..:

它是C中唯一可用于#defineif语句操作的结构,后面加一个分号,并且仍然在语句中使用.一个例子可能有帮助:

#define FOO(x) foo(x); bar(x)

if (condition)
    FOO(x);
else // syntax error here
    ...;

即使使用大括号也无济于事:

#define FOO(x) { foo(x); bar(x); }

if语句中使用它将要求您省略分号,这是违反直觉的:

if (condition)
    FOO(x)
else
    ...

如果你这样定义FOO:

#define FOO(x) do { foo(x); bar(x); } while (0)

那么以下语法是正确的:

if (condition)
    FOO(x);
else
    ....


@LarryF:问题是,如果您正在编写供其他人使用的头文件,则无法选择其他人如何使用您的宏.为了避免对用户造成意外的意外,您必须使用上述技术使您的宏行为与任何其他C语句的行为一样.
如果编码正确的话,我仍然认为这是UGLY和SLOPPY编码,并且可以避免.这可以追溯到一些常识C规则,总是在你的IF语句中使用卷曲,即使在IF之后只有一个操作.这应该是标准做法,IMVHO ......
不会`#define FOO(x)if(true){foo(x); 杆(X); } else void(0)`即使它更丑陋也可以工作?
@ user10607:是的,如果你的宏扩展是*表达式*的列表,那么这是有效的.但是,如果你想在扩展中包含一个`if`或`while`,那么这个技巧也行不通.
但是`#define FOO(x)foo(x),bar(x)`如何使用逗号代替分号.如果不这样做,这不会很好吗?
这个答案多么令人惊讶
@Max好的,如果您仍然对自己的问题有疑问,请提出新问题,而不是使用评论.谢谢.

2> Jere.Jones..:

这是一种简化错误检查并避免深层嵌套if的方法.例如:

do {
  // do something
  if (error) {
    break;
  }
  // do something else
  if (error) {
    break;
  }
  // etc..
} while (0);


或者使用`goto`.不,严重的说,`if(错误)转到错误;`和一个`错误:......`接近结尾似乎是一个更清洁的版本,对我来说完成同样的事情.
呃,将其纳入方法,并使用早期回报.
或者......只需使用do {} while(0).
@WChargin:您链接的文章中的"goto fail"代码也会因"中断"而失败.有人刚刚在那里复制了一条线.这不是goto的错.
@NiccoloM."被授予,goto不是错误,这实际上让它更有趣"

3> Martin v. Lö..:

它有助于将多个语句分组到一个语句中,因此类似函数的宏实际上可以用作函数.假设你有

#define FOO(n)   foo(n);bar(n)

你也是

void foobar(int n) {
  if (n)
     FOO(n);
}

然后这扩大到

void foobar(int n) {
  if (n)
     foo(n);bar(n);
}

请注意,第二个调用(bar(n))不再是if语句的一部分.

将两者都包装到do {} while(0)中,也可以在if语句中使用宏.


非常明确的答案.+1

4> 小智..:

有趣的是,要注意以下情况:在做{}而(0)循环不会为你工作:

如果你想要一个返回值的类函数宏,那么你将需要一个语句表达式:({stmt; stmt;})而不是do {} while(0):

#include 

#define log_to_string1(str, fmt, arg...) \
    do { \
        sprintf(str, "%s: " fmt, "myprog", ##arg); \
    } while (0)

#define log_to_string2(str, fmt, arg...) \
    ({ \
        sprintf(str, "%s: " fmt, "myprog", ##arg); \
    })

int main() {
        char buf[1000];
        int n = 0;

        log_to_string1(buf, "%s\n", "No assignment, OK");

        n += log_to_string1(buf + n, "%s\n", "NOT OK: gcc: error: expected expression before 'do'");

        n += log_to_string2(buf + n, "%s\n", "This fixes it");
        n += log_to_string2(buf + n, "%s\n", "Assignment worked!");
        printf("%s", buf);
        return 0;
}


这是GCC扩展.但是在C++ 11中,你可以用lambda做同样的事情.
推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有