最近在FFmpeg和sox源码中发现有#define do...while(0)的用法,不太能理解就查了下。发现在Linux内核中也有这些用法。

总结大概有以下几点:

  1. 空语句编译时会产生警告#define FOO do{ } while(0)
  2. 创建一个局部空间,可以在其中定义局部变量
  3. 在宏定义中使用复杂语法,单只产生单条语句而不是语句块
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

    // 这样调用上面的宏
    if (x > y)
      exch(x,y); // Branch 1
    else
      do_something(); // Branch 2

    // 但展开是这样
    if (x > y) { // 单分支if
      int tmp;
      tmp = x;
      x = y;
      y = tmp;
    }
     ; // 空语句
    else // 错误!!! "parse error before else"
      do_something();

    // 采用do while
    if (x > y)
      do {
      int tmp;
      tmp = x;
      x = y;
      y = tmp;
      } while(0);
    else
      do_something();

具体参考以下内核说明文档https://kernelnewbies.org/FAQ/DoWhile0

参考资料