LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2053|回复: 9

请教一下下面这个do while的用法?

[复制链接]
发表于 2005-9-1 11:13:14 | 显示全部楼层 |阅读模式

  1. #define INIT_LIST_HEAD(ptr) do { \
  2.         (ptr)->next = (ptr); (ptr)->prev = (ptr); \
  3. } while (0)
复制代码

是list.h中对INIT_LIST_HEAD宏的定义,它加这样一个do while有什么样的意义啊?
发表于 2005-9-1 11:27:59 | 显示全部楼层
嗯,内核里面经常这么用.
因为没有其他更简洁的方式定义这个宏
回复 支持 反对

使用道具 举报

发表于 2005-9-1 12:32:26 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2005-9-1 15:05:11 | 显示全部楼层
Post by haohao_h

  1. #define INIT_LIST_HEAD(ptr) do { \
  2.         (ptr)->next = (ptr); (ptr)->prev = (ptr); \
  3. } while (0)
复制代码

是list.h中对INIT_LIST_HEAD宏的定义,它加这样一个do while有什么样的意义啊?

===========================================

do-while语句使得定义的定义的宏在语义上等价于C的语句(可以吸收后面的';'号),
因此可以象其他C语句一样使用。

考虑下面这个宏:

#define swap(a, b) { int c = a; a = b; b = c; }

在if-else语句中将出现问题

if(a < b) swap(a, b);
else return a;

宏展开后成了这样:

if(a < b) { int c = a; a = b; b = c; };
else return a;

在if语句后面多了一个分号';',这显然不是我们需要的

因此,可以用do-while定义

#define swap(a, b) do { int c = a; a = b; b = c; } while(0)

这样的话展开就没有问题了

if(a < b) do { int c = a; a = b; b = c; } while(0);
else return a;
回复 支持 反对

使用道具 举报

发表于 2005-9-1 15:17:55 | 显示全部楼层
加入这个do{}while(0)是为了避免可能的某些编译器错误特别是宏里面定义了变量。
当编译器优化的时候就不会出错。

  例如我们定义一个LOG()宏

  #define LOG(level,fmt,args...)  do{\
     char buff[4096]; \
     bzero(buff,sizeof(buff));\
     snprintf(buff,sizeof(buff),fmt,##args);\
     fprintf(stderr,"my log %s\n",buff);\
  }while(0)
回复 支持 反对

使用道具 举报

发表于 2005-9-1 15:49:19 | 显示全部楼层
Post by missanda
加入这个do{}while(0)是为了避免可能的某些编译器错误特别是宏里面定义了变量。
当编译器优化的时候就不会出错。

  例如我们定义一个LOG()宏

  #define LOG(level,fmt,args...)  do{\
     char buff[4096]; \
     bzero(buff,sizeof(buff));\
     snprintf(buff,sizeof(buff),fmt,##args);\
     fprintf(stderr,"my log %s\n",buff);\
  }while(0)

这种说法倒是第一次见到,宏定义体里面难道不能定义变量吗?
回复 支持 反对

使用道具 举报

发表于 2005-9-1 16:44:38 | 显示全部楼层
是的。
因为标准的ANSI-C是不允许在语句后再定义变量的,(强语法约束)
所以有的时候为了简单想在函数的其他地方定义变量的情况只能在{后面,
编译器编译的时候一般会把变量提前到函数前去,以便在当前栈上分配空间。
  
例如

test(void)
{

     int var1 = 0;

     var1 = 1+2;

     int var2 = 0;


}
是不可以的。

但是

test(void)
{

     int var1 = 0;
     
     var1 = 1+2;

     {
         int var2 = 0;
     }


}

是可以的。



  这就是经常会看到用{}或者do{}while(0)的原因之一!.
  但是这并不是使用do{}while(0)或者{}的主要原因。

  Anda.
回复 支持 反对

使用道具 举报

发表于 2005-9-1 17:05:26 | 显示全部楼层
你那是很久以前的标准了吧? 我以前在vc上试过,确实不行.
但是我想c99标准是不会有这样的限制的.

另外,这里do{}while(0)事实上,主要是跟{}做比较,你却将它们放在一起?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-1 17:43:01 | 显示全部楼层
受教
回复 支持 反对

使用道具 举报

发表于 2005-9-1 19:16:18 | 显示全部楼层
Post by missanda
是的。
因为标准的ANSI-C是不允许在语句后再定义变量的,(强语法约束)
所以有的时候为了简单想在函数的其他地方定义变量的情况只能在{后面,
编译器编译的时候一般会把变量提前到函数前去,以便在当前栈上分配空间。
  
例如

test(void)
{

     int var1 = 0;

     var1 = 1+2;

     int var2 = 0;


}
是不可以的。

但是

test(void)
{

     int var1 = 0;
     
     var1 = 1+2;

     {
         int var2 = 0;
     }


}

是可以的。



  这就是经常会看到用{}或者do{}while(0)的原因之一!.
  但是这并不是使用do{}while(0)或者{}的主要原因。

  Anda.

这似乎不是do-while的主要原因
重要的是do-while(0)可以当作一个C语句看待
而{}则是复合语句,后面不能跟分号了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表