• 关于do...while();循环最后的分号。


    首先,在C语言中,与while有关的两个循环结构定义如下:

    1- while(条件) {...}

    2- do{...} while(条件);

    注意第2个循环最后的那个分号,为什么会有这个分号?因为第1个循环被作为一个整体,可以被编译器识别,而第2个循环,如果没有最后的分号,编译器就不知道while是修饰前面的语句,还是像第1个一样修饰后面的语句,这里的分号起到了断句,消除歧义的作用。

    这个分号在Linux内核代码中成为了一种所谓的编程技巧。

    在Linux内核中,可以看到这样的宏定义:

    #define MACRO_NAME do{...}while(0)

    这个宏执行的动作就是让{...}执行一次,可为什么非要这么定义? 看以下的情景:

    如果宏定义如此: #define MACRO_NAME a=10;b=20;

    if(...)

      MACRO_NAME;

    else

      ...;

    经过宏展开之后,变成:

    if(...)

      a=10;b=20;;

    else

      ...;

    编译就会出错,因为找不到else匹配的if。这是因为我们宏定义的时候,没有把定义的语句做成一个整体,导致宏展开的时候影响了上下文的语法结构。

    那么,你一定会想到为宏定义加上一对大括号:#define MACRO_NAME {a=10;b=20;}

    展开之后,为:

    if(...)

      {a=10;b=20};

    else

      ...;

    这仍然会出现else不匹配的问题,因为那个红色的分号仍然在大括号外面。而这个红色分号的存在是因为我们在使用宏的时候,仍然习惯于采用C语言的语法。于是,我们想到这么使用宏:

    if(...)

      MACRO_NAME

    else

      ...;

    可这样,看起来似乎又不那么自然,起码表面上看不符合C语言的语法形式。

    归根结底,最好的方式是,在出现宏调用的地方,把整个宏调用包括分号用一对大括号括起来。如下:

    if(...)

      {MACRO_NAME;}

    else

      ...;

    这样,无论你在定义宏的时候是否加上分号,只要在调用宏的时候按照C语言的语法加上分号,就绝对不会出错,也不必在宏定义中

    使用奇怪的do{...}while(0)循环了。

    小结:

    其实这种做法和采用do{...}while(0)定义宏的做法目的本质上一样,都是为了让编译器把宏调用处的分号与宏调用看作一个整体,只不过我是显式的

    利用一对大括号直接括起来,而它是隐式的利用了C语言中的do{...}while(0);语法结构。采用do{...}while(0)的方式看起来有些古怪,但更简练。

  • 相关阅读:
    解决clickonce不支持administer权限问题
    好好了解一下Cookie(强烈推荐)
    Cookie的存储读取删除修改 (cookie.Expires读取永远是零时间)
    14VUE插槽
    13VUE非父子组件传值
    1VUE学习方法
    11VUE监听原生事件
    10VUE,组件参数校验,组件3
    9,Vue组件2
    8.VUE计数器,基于组件
  • 原文地址:https://www.cnblogs.com/smwikipedia/p/1353568.html
Copyright © 2020-2023  润新知