【C语言编程规范】宏定义的多条语句使用do-while(0)封装

有时候,你会发现,C语言中很多宏定义中使用了do-while(0)
比如,下面的这两个多条语句的宏定义(来源于头文件math.h)

/* Get a 32 bit int from a float.  */
#ifndef GET_FLOAT_WORD
# define GET_FLOAT_WORD(i,d)					\
do {								\
  ieee_float_shape_type gf_u;					\
  gf_u.value = (d);						\
  (i) = gf_u.word;						\
} while (0)
#endif

/* Set a float from a 32 bit int.  */
#ifndef SET_FLOAT_WORD
# define SET_FLOAT_WORD(d,i)					\
do {								\
  ieee_float_shape_type sf_u;					\
  sf_u.word = (i);						\
  (d) = sf_u.value;						\
} while (0)
#endif

有些人可能不理解,为什么要使用do-while(0)呢
不使用do-while(0)会有什么问题吗

下面我来做一下简单的说明

使用do-while(0)的目的是确保宏能被完整的执行
因为宏是简单的代码替换
对于含有多条语句的宏
如果不使用do-while(0)的结构
在某些情况下宏展开会出现错误

错误示例1

#define CUBE(a, b) \
    a = a * a * a; \
    b = b * b * b;

对于上面这种含有多条语句的宏定义
该宏没有使用大括号{}结构,没有使用if(0){}结构,也没有使用do-while(0)结构
如果使用下面的代码调用宏,就会出问题

if (a + b > 0)
    CUBE(a, b);

本意是在a+b>0的情况下才会对a和b进行重新赋值
但是在实际上宏展开之后
由于if语句没有使用大括号{}
不管a+b>0条件是否成立
b = b * b * b;的语句都会执行,造成错误

错误示例2

#define CUBE(a, b) \
{
    a = a * a * a; \
    b = b * b * b; \
}

虽然使用了大括号{}的结构,但是在遇到下面这种情况还是会有问题

if (a + b > 0)
	CUBE(a, b);
else
	a = 0;

宏展开之后如下:

if (a + b > 0)
{
    a = a * a * a;
    b = b * b * b;
};
else
	a = 0;

由于宏后面有个分号,会造成else匹配出现问题,造成错误

当然,如果你严格执行C的编程规范
上例中if后面的语句使用大括号{}括起来(哪怕只有一条语句)
也可以避免出现问题

但是我们还是强烈建议,对于多条语句的宏定义,要使用do-while(0)结构

#define CUBE(a, b)       \
do {                     \
    a = a * a * a;       \
    b = b * b * b;       \
} while (0)

注意:
并不是所有的含有多条语句的宏定义都可以直接加do-while(0)结构
在含有break,goto等跳转语句的宏定义中一定要厘清代码的逻辑
如果加了do-while(0)有可能会改变代码逻辑
甚至会出现无法跳转出去的情况
尤其是在做代码整改的时候,要格外小心!!!

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值