宏与分号

    技术2022-05-19  22

    细节决定成败!

    如果留心的话,可以看到 linux内核代码经常有这么奇怪的宏定义:

    引用 #define wait_event(wq, condition)                                  do {                                 if ( condition)                  break;         __wait_event( wq , condition); } while ( 0) 上面的宏中,while(0) 后是没有分号的,而且这个宏的 do 里执行一次,那为什么要这么定义呢? 这是因为,在程序里使用宏时,我们按照会在语句的后面加个分号 ; ,如: wait_event(wq,conditon) ; 展开后,成为: 引用 do {                                 if ( condition)                  break;         __wait_event( wq , condition); } while ( 0) ; 由此可见,分号自己加上了。假如在宏定义中已在 while(0) 后添加了分号。那么对于在程序中,单独的调用这个宏,不管在宏的后面是否添加分号,那都是可以的;如果是添加了分号,那就是执行了一个空语句。 但是对于 if  ... else ... 结构,情况就不一样了,像下面的程序: 引用 #include <stdio.h> int condition = 0; #define wait_condition         / do {                /     if (condition == 10)    /         break;        /     condition++;        /     sleep(1);        / } while (0);            / int main() {     int k = 1;     if ( k == 1)         wait_condition ;       /*添加了分号编译会报错*/     else         printf ( "hello world /n ");     printf ( "%d /n " , condition);     return ( 0); } 编译报错: 引用 [beyes@localhost programming]$ gcc -g temp.c -o temp.exe temp.c: 在函数‘main’中: temp.c:19: 错误:‘else’没有对应的‘if’ 如果在程序中将 wait_condition;后的分号去掉,那就可以编译通过了,但这看上去就不符合 C 语言的表达式习惯。所以,在宏定义里的 while(0) 后不需要添加分号。然而,不管宏里加不加分号,但在程序里如下使用,也不会出现问题: 引用 { wait_condition ; } 将宏语句用大括号括起来,这样整个宏将被当成一个整体看待,所以也是正确的。 那为什么会定义 do ... while(0)  这样的形式呢?原因是,这样做会让程序的看起来更加简洁清晰(在程序中使用大括号把一个单独的宏括起来多少总觉得有些碍眼)。

    最新回复(0)