摘抄自: <<Linux设备驱动开发详解(第二版)>>

在 Linux 内核中,经常会看到do{} while(0)这样的语句,许多人开始都会疑惑,认为do{} while(0)毫无意义,因为它只会执行一次,加不加do{}  while(0)效果是完全一样的,其实 do {}
while(0)的用法主要用于宏定义中。
这里用一个简单点的宏来演示:
#define SAFE_FREE(p) do{ free(p); p = NULL;} while(0)
假设这里去掉 do...while(0),即定义 SAFE_DELETE 为:
#define SAFE_FREE(p) free(p); p = NULL;
那么以下代码
if(NULL != p)
    SAFE_DELETE(p)
else
    .../* do something */
会被展开为:
if(NULL != p)
    free(p); p = NULL;  
else
    .../* do something */
展开的代码中存在两个问题。
(1)因为 if 分支后有两个语句,导致 else 分支没有对应的 if,编译失败。
(2)假设没有 else 分支,则 SAFE_FREE 中的第二个语句无论 if 测试是否通过,都会执行。
的确,将 SAFE_FREE 的定义加上{}就可以解决上述问题了,即:
#define SAFE_FREE(p) { free(p); p = NULL;}
这样,代码:
if(NULL != p)
    SAFE_DELETE(p)
else
    ... /* do something */
会被展开为:
if(NULL != p)
   { free(p); p = NULL; }
else
    ... /* do something */
但是,在 C 程序中,每个语句后面加分号是一种约定俗成的习惯,那么,如下代码:
if(NULL != p)
    SAFE_DELETE(p);
else
    ... /* do something */
将被扩展为:
if(NULL != p)
   { free(p); p = NULL; };
else
    ... /* do something */
这样,else 分支就又没有对应的 if 了,编译将无法通过。假设用了 do {} while(0),情况就不一样了,同样的代码会被展开为:
if(NULL != p)
   do{ free(p); p = NULL;} while(0);
else
    ... /* do something */
不会再出现编译问题。do while(0)的使用完全是为了保证宏定义的使用者能无编译错误地使用宏,它不对其使用者做任何假设。

Linux中的do{...} while(0)的更多相关文章

  1. LINUX中ORACLE 11.2.0.1 升级到11.2.0.4

    11.2.0.4补丁号13390677,共7个文件,分别是 其中1&2是db,3是grid,4是client,5是gateways,6是example,7是deinstall 上传安装介质并解 ...

  2. linux中shell变量$#,$@,$*,$?,$$,$!,$_,$0,$1,$2的含义解释

    变量说明:    $$    Shell本身的PID(ProcessID)    $!    Shell最后运行的后台Process的PID    $?    最后运行的命令的结束代码(返回值)    ...

  3. 在Linux中安装ASPNET.Core3.0运行时

    # 以下示例适用于x64位runtime v3.0.0 mkdir /runtimes cd /runtimes wget https://download.visualstudio.microsof ...

  4. linux中shell变量$#,$@,$0,$1,$2的含义解释

    linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行 ...

  5. linux中shell变量$#,$@,$0,$1,$2的含义解释

    linux中shell变量$#,$@,$0,$1,$2的含义解释 linux中shell变量$#,$@,$0,$1,$2的含义解释:  变量说明:  $$  Shell本身的PID(ProcessID ...

  6. Linux中Zabbix4.0的搭建

    Zabbix简介 Zabbix是一个高度集成的企业级开源网络监控解决方案,与Cacti.nagios类似,提供分布式监控以及集中的web管理界面.zabbix具备常见商业监控软件所具备的功能,例如主机 ...

  7. Linux中shell变量$0,$?等含义

    linux中shell变量$#,$@,$0,$1,$2的基本含义: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行 ...

  8. 【转】linux中shell变量$#,$@,$0,$1,$2的含义解释

    原文网址:http://www.cnblogs.com/fhefh/archive/2011/04/15/2017613.html linux中shell变量$#,$@,$0,$1,$2的含义解释: ...

  9. 【Shell】linux中shell变量$#,$@,$0,$1,$2的含义解释 && set 关键字使用

    linux中shell变量$#,$@,$0,$1,$2的含义解释   摘抄自:ABS_GUIDE 下载地址:http://www.tldp.org/LDP/abs/abs-guide.pdf linu ...

随机推荐

  1. unity中生成一个GUI格子(始终居中)

    1.Script程序 using UnityEngine; using System.Collections; public class GUITest : MonoBehaviour { [Seri ...

  2. js-ES6学习笔记-对象的扩展

    1.ES6允许直接写入变量和函数,作为对象的属性和方法.这种写法用于函数的返回值,将会非常方便.CommonJS模块输出变量,就非常合适使用简洁写法. var ms = {}; function ge ...

  3. node 搭建静态服务

    对于Node.js新手,搭建一个静态资源服务器是个不错的锻炼,从最简单的返回文件或错误开始,渐进增强,还可以逐步加深对http的理解. 基本功能 不急着写下第一行代码,而是先梳理一下就基本功能而言有哪 ...

  4. .net中反射与IOC容器实现

    反射还是很有用的,比如IOC容器基本上都是通过反射实现的. IOC是什么 IOC:Inversion of Control 控制反转是一种是面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度 ...

  5. 【CLR Via C#】15 枚举类型与位类型

    1.基础 枚举类型(enumerated types)定义了一组“符号名称/值”配对. 枚举类型是值类型,每个枚举类型都是从System.Enum派生的,而System.Enum又是从System.V ...

  6. Python学习笔记之——requests库

    requests库一个优雅而简单的用于Python的HTTP库,可以极大的简化我们发送http请求及获取响应的代码. requests是python的第三方库,所以使用之前需要先安装. 1.安装之后就 ...

  7. Flutter之搜索电影

    搜索使用的是豆瓣电影API https://developers.douban.com/wiki/?title=movie_v2#subject 效果 代码: https://github.com/z ...

  8. Angular调用父Scope的函数

    app.directive('toggle', function(){ return { restrict: 'A', template: '<a ng-click="f()" ...

  9. iOS 开发之环形倒计时进度条(虚线/实线)

    代码很简单,一看便知.这里为顺时针,若想要逆时针,clockwise改为0,还需更改起始角度和终点角度. 源码地址:https://github.com/LfyDragon/CountDown 直接上 ...

  10. Java J2EE读取配置文件

    package com; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.naming.InitialCon ...