`
weiyinchao88
  • 浏览: 1235029 次
文章分类
社区版块
存档分类
最新评论

内核里的do{}while(0)

 
阅读更多

为啥内核里有这么多 do{ }while(0) 的宏啊?一开始我也好不明白。感觉不出用了会有什么效果。不过明白之后就知道它的好处了。好处就在于多语句的宏。

#define FOO(x)	print(”arg is %sn”,x);do_something(x);

在代码中使用:

if(2==blah)

	FOO(blah);

预编译展开后:

if(2==blah)

	print(”arg is %sn”,blah);

do_something(blah);

看到了吧,do_something函数已经脱离了if语句的控制了。这可不是我们想要的。使用do{}while(0);就万无一失了。

if (2== blah)

  do {

	printf(”arg is %sn”, blah);

	do_something(blah);

  } while (0);

当然你也可以使用下面这种形式:

#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

但是它在if-else语句中会出现问题。如:
if (x > y)

	exch(x,y);          // Branch 1

else

	do_something();     // Branch 2

展开后:

if (x > y) {                // Single-branch if-statement!!! 

	int tmp;            // The one and only branch consists

	tmp = x;            // of the block.

	x = y;

	y = tmp;v};                           // empty statementelse          

 // ERROR!!!   “parse error before else”do_something();

看到了吧,else成了语法错误了。使用do{}while(0)就不会有这个问题了。

if (x > y)

do {

	int tmp;

	tmp = x;

	x = y;

	y = tmp;

} while(0);

else

	do_something();

嗯,现在明白之后,自己的代码也记得用啊!

分享到:
评论

相关推荐

    5152单片机proteus仿真和源码用do-while语句控制P0口8位LED流水点亮

    ### 5152单片机Proteus仿真与源码详解:利用do-while语句控制P0口实现8位LED流水灯效果 #### 一、基础知识介绍 1. **5152单片机简介**: - 5152单片机是一种基于8051内核的单片机,它继承了8051的所有特性,并在...

    c++中do{…}while(0)的意义和用法

    实际上,do{…}while(0)的作用远大于美化你的代码。查了些资料,总结起来这样写主要有以下几点好处: 1、辅助定义复杂的宏,避免引用的时候出错: 举例来说,假设你需要定义这样一个宏: 代码如下: #define ...

    浅谈do {...} while (0) 在宏定义中的作用

    "do {...} while (0)"结构在宏定义中的运用就是一种解决这些问题的技巧。 首先,让我们理解一下`do {...} while (0)`的基本原理。这个结构实际上创建了一个只有一个迭代的循环,但它的主要目的并不是进行真正的循环...

    Linux内核延时研究与函数代码分析

    while (tv.tv_usec - start ) { do_gettimeofday(&tv); } } ``` 2. 使用sleep_on_timeout函数实现延迟: ```c extern inline long sleep_on_timeout(wait_queue_head_t *q, signed long timeout) { signed long ...

    Linux1.0内核源码分析

    } while (0) ``` 这种方式更灵活,可以用于动态创建的链表头。 #### 六、链表节点的插入 链表节点的插入主要包括三种情况: 1. **中间节点插入**: ```c static inline void __list_add(struct list_head *...

    Linux内核编码风格(译文)

    一般来说,结束大括号应该独占一行,除非它后面直接跟着同一语句的剩余部分(如do语句中的while或if语句中的else)。在只有一个单独语句的情况下,可以不使用大括号,但条件语句的分支中应保持一致,即使分支只包含...

    Linux内核通知(广播)机制.pdf

    } while (0) ``` - **阻塞型通知链表初始化**: ```c #define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \ rwsem_init(&(name)->rwsem); \ (name)->head = NULL; \ } while (0) ``` - **原始通知链表初始化*...

    浅谈do {…} while (0) 在宏定义中的作用

    如果你是一名C程序员,你肯定很熟悉宏,它们非常强大,如果正确使用可以让你的工作事半功倍。...在Linux内核和其它一些著名的C库中有许多使用do{…}while(0)的宏定义。这种宏的用途是什么?有什么好处? Google的Robert

    vfp WebBrowser(支持内核是ie 和 edge)

    DO WHILE oWebBrowser.Busy OR NOT oWebBrowser.ReadyState = READYSTATE_COMPLETE SLEEP(100) ENDDO oWebBrowser.Document.InvokeScript("myJavaScriptFunction") ``` 这段代码首先加载指定的网页,等待...

    Linux内核编码规范.txt

    - **关键字后的空格**:如`if`, `switch`, `case`, `for`, `do`, `while`等关键字后应有空格。 ##### 3. 多行语句 - **多行语句的拆分**:例如,长的函数调用可以拆分成多行,每行参数对齐,以增强可读性。 ```c ...

    Android内核的简单分析 Android 内核

    while [ $? -eq 1 ]; do echo "============sync failed, re-sync again=====" sleep 3 repo sync done ``` #### 四、Android内核结构 在Android的`kernel`子目录中包含了基于Linux-2.6.25的内核源码。通过...

    5-ARM上的Linux内核及启动过程

    宏定义中的`do...while(0)`结构确保了即使参数为空也不会发生错误。 ```c #define DUMP_WRITE(addr, nr) \ do {memcpy(bufp, addr, nr); bufp += nr;} while(0) ``` - **`OFFSETOF` 宏定义**:用于计算结构体...

    Linux内核线程编程方法

    创建后的内核线程会一直运行,除非调用`do_exit`函数主动退出,或者通过`kthread_stop`发送信号来结束其运行。 编写内核线程的函数通常是一个无限循环,使用`set_current_state`和`schedule_timeout`来控制线程的...

    linux-0.11 [内核源代码带英文注解]

    (void) open("/dev/tty0",O_RDWR,0); (void) dup(0); (void) dup(0); _exit(execve("/bin/sh",argv,envp)); } while (1) if (pid == wait(&i)) break; printf("\n\rchild %d died with ...

    Linux内核代码风格.pdf

    这适用于`if`、`switch`、`for`、`while`和`do`语句。函数体的大括号则另起一行。结束大括号通常单独一行,但`do-while`或`if-else`结构中的大括号紧接在相关语句后。 5. **避免空格滥用**:除了注释、文档和...

    深入分析 Linux 内核链表

    } while (0) ``` 例如,我们可以通过以下方式初始化一个名为 `nf_sockopts` 的链表: ```c LIST_HEAD(nf_sockopts); // 或者 INIT_LIST_HEAD(&nf_sockopts); ``` 初始化后,`nf_sockopts` 的 `next` 和 `prev` ...

    算法学习资料:详解Linux内核之双向循环链表

    } while (0) LIST_HEAD() 宏可以同时完成定义链表头,并初始化这个双循环链表为空。静态定义一个 list_head 类型变量,该变量一定为头节点。name 为 struct list_head{} 类型的一个变量,&(name) 为该结构体变量的...

    Linux中的内核链表实例详解

    Linux中的内核链表实例详解 链表中一般都要进行初始化、插入、删除、显示、释放链表,寻找节点这几个操作,下面我对这几个操作...} while (0) // ptr为struct list_head,其中包括两个指针next和prev,这里已经可以看

    linux内核链表

    } while(0) // 使用示例: INIT_LIST_HEAD(&nf_sockopts); ``` ##### 2.2 插入与删除 对于链表的插入操作,Linux内核提供了两种主要的方法:`list_add()`和`list_add_tail()`,分别用于在链表头部和尾部插入新的...

Global site tag (gtag.js) - Google Analytics