• 宏与分号


    转自:宏与分号

    细节决定成败!

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

    引用
    #define wait_event(wq, condition)                                  
    do {                         
            if (condition)  
                    break;
            __wait_event(wq, condition);
    } while (0)
    View Code

    上面的宏中,while(0) 后是没有分号的,而且这个宏的 do 里执行一次,那为什么要这么定义呢?

    这是因为,在程序里使用宏时,我们按照会在语句的后面加个分号 ; ,如:
    wait_event(wq,conditon);
    展开后,成为:

    引用
    do {                         
            if (condition)  
                    break;
            __wait_event(wq, condition);
    } while (0);
    View Code

    由此可见,分号自己加上了。假如在宏定义中已在 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);
    }
    View Code

    编译报错

    引用
    [beyes@localhost programming]$ gcc -g temp.c -o temp.exe
    temp.c: 在函数‘main’中:
    temp.c:19: 错误:‘else’没有对应的‘if
    View Code

    如果在程序中将 wait_condition;后的分号去掉,那就可以编译通过了,但这看上去就不符合 C 语言的表达式习惯。所以,在宏定义里的 while(0) 后不需要添加分号。
    然而,不管宏里加不加分号,但在程序里如下使用,也不会出现问题:

    引用
    {wait_condition; }
    View Code

    将宏语句用大括号括起来,这样整个宏将被当成一个整体看待,所以也是正确的。

    那为什么会定义 do ... while(0)  这样的形式呢?
    原因是,这样做会让程序的看起来更加简洁清晰(在程序中使用大括号把一个单独的宏括起来多少总觉得有些碍眼)。


    分割线上是原文。个人感觉分析的不够透彻,为此写下个人感想。

    上代码,每段代码分为  源码 + 编译情况 + 预处理后的.i文件。所有代码均在Linux环境下实验

    正确代码

    #include <stdio.h>
    #include <stdlib.h>
    int condition = 0;
    
    #define wait_condition  
    do {
        if (condition == 10)
            break;
        condition++;
        sleep(1);
    } while (0)
    
    int main()
    {
        int k = 1;
        wait_condition; 
        if (k == 1)
            wait_condition;       /*添加了分号编译会报错*/
        else
            printf ("hello world/n");
        
        printf ("%d/n", condition);
        return (0);
    }
    
    编译OK
    
    # 1 "/usr/include/bits/stdlib-float.h" 1 3 4
    # 952 "/usr/include/stdlib.h" 2 3 4
    # 964 "/usr/include/stdlib.h" 3 4
    
    # 3 "hello.c" 2
    int condition = 0;
    # 13 "hello.c"
    int main()
    {
        int k = 1;
        do { if (condition == 10) break; condition++; sleep(1);} while (0);
        if (k == 1)
            do { if (condition == 10) break; condition++; sleep(1);} while (0);
        else
            printf ("hello world/n");
    
        printf ("%d/n", condition);
        return (0);
    }
    View Code

    以下均为错误代码

    #include <stdio.h>
    #include <stdlib.h>
    int condition = 0;
    
    #define wait_condition  
    do {
        if (condition == 10)
            break;
        condition++;
        sleep(1);
    } while (0);
    
    int main()
    {
        int k = 1;
        wait_condition; 
        if (k == 1)
            wait_condition;       /*添加了分号编译会报错*/
        else
            printf ("hello world/n");
        
        printf ("%d/n", condition);
        return (0);
    }
    
    
    编译报错
    hello.c: In function ‘main’:
    hello.c:19:5: error: ‘else’ without a previous ‘ifelse
         ^
    
    # 1 "/usr/include/bits/stdlib-float.h" 1 3 4
    # 952 "/usr/include/stdlib.h" 2 3 4
    # 964 "/usr/include/stdlib.h" 3 4
    
    # 3 "hello.c" 2
    int condition = 0;
    # 13 "hello.c"
    int main()
    {
        int k = 1;
        do { if (condition == 10) break; condition++; sleep(1);} while (0);;
        if (k == 1)
            do { if (condition == 10) break; condition++; sleep(1);} while (0);;
        else
            printf ("hello world/n");
    
        printf ("%d/n", condition);
        return (0);
    }
    View Code
    #include <stdio.h>
    #include <stdlib.h>
    int condition = 0;
    
    #define wait_condition  
        if (condition == 10)
            break;
        condition++;
        sleep(1);
    
    int main()
    {
        int k = 1;
        wait_condition; 
        if (k == 1)
            wait_condition;       /*添加了分号编译会报错*/
        else
            printf ("hello world/n");
        
        printf ("%d/n", condition);
        return (0);
    }
    
    
    编译报错
    hello.c: In function ‘main’:
    hello.c:7:9: error: break statement not within loop or switch
             break;
             ^
    hello.c:14:5: note: in expansion of macro ‘wait_condition’
         wait_condition; 
         ^
    hello.c:7:9: error: break statement not within loop or switch
             break;
             ^
    hello.c:16:9: note: in expansion of macro ‘wait_condition’
             wait_condition;       /*添加了分号编译会报错*/
             ^
    hello.c:17:5: error: ‘else’ without a previous ‘if’
         els
         
    # 1 "/usr/include/bits/stdlib-float.h" 1 3 4
    # 952 "/usr/include/stdlib.h" 2 3 4
    # 964 "/usr/include/stdlib.h" 3 4
    
    # 3 "hello.c" 2
    int condition = 0;
    
    int main()
    {
        int k = 1;
        if (condition == 10) break; condition++; sleep(1);;
        if (k == 1)
            if (condition == 10) break; condition++; sleep(1);;
        else
            printf ("hello world/n");
    
        printf ("%d/n", condition);
        return (0);
    }
    View Code
    #include <stdio.h>
    #include <stdlib.h>
    int condition = 0;
    
    #define wait_condition  
        if (condition == 10)
            break;
        condition++;
        sleep(1)
    
    int main()
    {
        int k = 1;
        wait_condition; 
        if (k == 1)
            wait_condition;       /*添加了分号编译会报错*/
        else
            printf ("hello world/n");
        
        printf ("%d/n", condition);
        return (0);
    }
    
    
    编译报错
    hello.c: In function ‘main’:
    hello.c:7:9: error: break statement not within loop or switch
             break;
             ^
    hello.c:14:5: note: in expansion of macro ‘wait_condition’
         wait_condition; 
         ^
    hello.c:7:9: error: break statement not within loop or switch
             break;
             ^
    hello.c:16:9: note: in expansion of macro ‘wait_condition’
             wait_condition;       /*添加了分号编译会报错*/
             ^
    hello.c:17:5: error: ‘else’ without a previous ‘ifelse
         ^
    
         # 1 "/usr/include/bits/stdlib-float.h" 1 3 4
    # 952 "/usr/include/stdlib.h" 2 3 4
    # 964 "/usr/include/stdlib.h" 3 4
    
    # 3 "hello.c" 2
    int condition = 0;
    
    int main()
    {
        int k = 1;
        if (condition == 10) break; condition++; sleep(1);
        if (k == 1)
            if (condition == 10) break; condition++; sleep(1);
        else
            printf ("hello world/n");
    
        printf ("%d/n", condition);
        return (0);
    }
    View Code
    #include <stdio.h>
    #include <stdlib.h>
    int condition = 0;
    
    #define wait_condition  
        if (condition == 10)
            return;
        condition++;
        sleep(1)
    
    int main()
    {
        int k = 1;
        wait_condition; 
        if (k == 1)
            wait_condition;       /*添加了分号编译会报错*/
        else
            printf ("hello world/n");
        
        printf ("%d/n", condition);
        return (0);
    }
    
    
    编译报错
    hello.c: In function ‘main’:
    hello.c:17:5: error: ‘else’ without a previous ‘ifelse
    
         
    # 1 "/usr/include/bits/stdlib-float.h" 1 3 4
    # 952 "/usr/include/stdlib.h" 2 3 4
    # 964 "/usr/include/stdlib.h" 3 4
    
    # 3 "hello.c" 2
    int condition = 0;
    
    int main()
    {
        int k = 1;
        if (condition == 10) return; condition++; sleep(1);
        if (k == 1)
            if (condition == 10) return; condition++; sleep(1);
        else
            printf ("hello world/n");
    
        printf ("%d/n", condition);
        return (0);
    }
    View Code
    #include <stdio.h>
    #include <stdlib.h>
    int condition = 0;
    
    #define wait_condition  
        if (condition == 10)
            return;
        condition++;
        sleep(1);
    
    int main()
    {
        int k = 1;
        wait_condition; 
        if (k == 1)
            wait_condition;       /*添加了分号编译会报错*/
        else
            printf ("hello world/n");
        
        printf ("%d/n", condition);
        return (0);
    }
    
    
    编译报错
    llo.c:17:5: error: ‘else’ without a previous ‘ifelse
         ^
    
    # 1 "/usr/include/bits/stdlib-float.h" 1 3 4
    # 952 "/usr/include/stdlib.h" 2 3 4
    # 964 "/usr/include/stdlib.h" 3 4
    
    # 3 "hello.c" 2
    int condition = 0;
    
    int main()
    {
        int k = 1;
        if (condition == 10) return; condition++; sleep(1);;
        if (k == 1)
            if (condition == 10) return; condition++; sleep(1);;
        else
            printf ("hello world/n");
    
        printf ("%d/n", condition);
        return (0);
    }
    View Code

    我给出的结论:

    如果带参宏,宏体有判断。请一定要加上do while(0),而且不能再while(0)后面加;

     这种情况报找不到if是因为多出来的那个;造成的
    单独;表示一句话,他隔开了else
     这种情况的找不到else不是由于;造成的
     从这句话开始就隔断了else。
    C认为什么是语句?
    ①int a=10;  这种有指令内容,有分号,是一条语句。
    ② ;  这种也是一句话,一条语句。只不过事空语句
    说白了,C判断是不是语句实际上是在查 ;
     
  • 相关阅读:
    NIO通道的学习笔记
    Struts学习笔记(启动过程)
    Struts2学习笔记(ResultType)
    11
    编写类String的构造函数、析构函数和赋值函数(转载)
    new与malloc的区别
    不用判断语句,求两个数中大的那个
    delete p和delete[] p的区别(转)
    (转)虚函数和纯虚函数区别
    不借助第三个变量交换两个整数的值
  • 原文地址:https://www.cnblogs.com/kelamoyujuzhen/p/9490666.html
Copyright © 2020-2023  润新知