c语言宏定义错误案例分析

#define DLT645_READ_FLOAT_TO_DOUBLE(CHAN, FUNC, DOUBLE_DEST) \
	{ \
		float float_val; \
		if (chan_dlt645_read_data(CHAN, FUNC, (unsigned char*)&float_val) < 0) { \
			-1; \
		} else { \
			DOUBLE_DEST = float_val; \
			0; \
		} \
	}

分析:

  1. 宏的返回值:宏并没有真正的返回值的概念,所以在-1;0;这两个地方,它们并不会像函数一样被返回。您可能的意图是希望在chan_dlt645_read_data函数调用失败的时候返回-1,成功的时候返回0,但是这样的写法并不能达成这个目的。

  2. 不适当的大括号使用:该宏定义的开始和结束处出现了大括号,这可能在某些使用场景下会导致问题。例如在if...else...语句中使用该宏可能会引发语法错误。

改进:

RESULT是由用户提供的变量,用来接收返回的结果。同时,添加了do...while(0)结构,可以避免宏在某些场景下的使用出现问题。最后,我们使用(double)float_val进行了强制类型转换,以确保将其赋值给DOUBLE_DEST时不会出现问题。

#define DLT645_READ_FLOAT_TO_DOUBLE(CHAN, FUNC, DOUBLE_DEST, RESULT) \
    do { \
        float float_val; \
        if (chan_dlt645_read_data(CHAN, FUNC, (unsigned char*)&float_val) < 0) { \
            RESULT = -1; \
        } else { \
            DOUBLE_DEST = (double)float_val; \
            RESULT = 0; \
        } \
    } while(0)

为什么要使用do...while(0)结构?

如果不使用do...while(0)结构,那么在使用这个宏的时候可能会碰到问题。这是因为预编译器在预处理宏的时候,会直接进行文本替换,不会添加额外的;(分号)或者 {}(大括号)

下面是一个例子:

 if (condition)
    DLT645_READ_FLOAT_TO_DOUBLE(CHAN, FUNC, DOUBLE_DEST, RESULT);
 else 
    // other code

在这个例子中,如果你的宏定义不使用do...while(0)结构,在预编译器进行宏替换之后,代码变为:

if (condition)
    float float_val; 
    if (chan_dlt645_read_data(CHAN, FUNC, (unsigned char*)&float_val) < 0) 
        RESULT = -1; 
    else {
        DOUBLE_DEST = (double)float_val; 
        RESULT = 0; 
    };
 else
    // other code

这样的代码会导致编译错误,因为if只控制到了第一句,其他的代码都在if的控制范围之外。

但是如果我们使用do...while(0),通过预编译器的替换之后,代码变为:

if (condition)
    do {
        float float_val; 
        if (chan_dlt645_read_data(CHAN, FUNC, (unsigned char*)&float_val) < 0) 
            RESULT = -1;
        else {
            DOUBLE_DEST = (double)float_val; 
            RESULT = 0; 
        } 
    } while(0);
 else
    // other code

这样的代码不会有编译错误。所以,使用do...while(0)可以提高宏的安全性,让宏在各种场景中都能正确工作。

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值