如何用多行C宏实现位移位?编译报错的修正方法
宏编译错误解决:移除if语句,改用合法表达式实现
为什么会报错?
你这个宏里直接用if语句,编译时就会出“expected identifier before if”错误——因为宏外层加了括号,是当作表达式来用的,但if是流程控制语句,只能放在代码块里,不能塞进表达式上下文里。宏是纯文本替换,展开后if直接出现在表达式位置,完全不符合C语法规则。
两种正确实现方式
方法1:嵌套三目运算符(适合少量告警)
用三目运算符?:代替if,它是表达式,能合法放在宏里:
#define ALARM_0 0x00 #define ALARM_1 0x01 #define ALARM_2 0x02 #define ALARM_4 0x03 #define ALARM_3 0x04 #define ALARM_5 0x05 #define ALARM_6 0x06 #define ALARM_7 0x07 #define ALARM_8 0x08 #define ALARM_9 0x09 #define ACTIVE_ALARM_BITS(a) \ ((a) == ALARM_0 ? ((a) >> 4) : \ (a) == ALARM_1 ? ((a) << 3) : \ (a) == ALARM_2 ? ((a) << 3) : \ (a) == ALARM_3 ? ((a) << 7) : \ /* 剩下的告警补对应逻辑,最后加默认值 */ 0x00)
注意:
- 每个
(a)都要套括号,防止参数是表达式时被运算优先级坑 - 必须加最后那个默认分支,不然没匹配到的话会触发语法报错
- 用
\换行时,后面别留多余空格,不然会编译出错
方法2:查找表(告警多的时候更省心)
如果告警数量多,直接整个数组存好移位结果,用宏查表就行,逻辑清晰还高效:
#define ALARM_0 0x00 #define ALARM_1 0x01 #define ALARM_2 0x02 #define ALARM_4 0x03 #define ALARM_3 0x04 #define ALARM_5 0x05 #define ALARM_6 0x06 #define ALARM_7 0x07 #define ALARM_8 0x08 #define ALARM_9 0x09 // 索引对应ALARM_x的值,数组元素是移位后的结果 static const uint8_t alarm_shift_table[] = { ALARM_0 >> 4, // 对应ALARM_0 ALARM_1 << 3, // 对应ALARM_1 ALARM_2 << 3, // 对应ALARM_2 0x00, // 对应ALARM_4(自行补充需要的移位值) ALARM_3 << 7, // 对应ALARM_3 0x00, // 对应ALARM_5 0x00, // 对应ALARM_6 0x00, // 对应ALARM_7 0x00, // 对应ALARM_8 0x00 // 对应ALARM_9 }; #define ACTIVE_ALARM_BITS(a) (alarm_shift_table[(a)])
以后加新告警,直接在数组里加对应位置的结果就行,不用改宏的逻辑,维护起来方便多了。
非要用if的话(不推荐)
如果硬要在宏里用if,得把宏包装成代码块,但这时候宏不能直接当表达式用,得传个变量存结果:
#define ACTIVE_ALARM_BITS(a, result) do { \ if((a) == ALARM_0) (result) = (a) >> 4; \ else if((a) == ALARM_1) (result) = (a) << 3; \ else if((a) == ALARM_2) (result) = (a) << 3; \ else if((a) == ALARM_3) (result) = (a) << 7; \ else (result) = 0x00; \ } while(0) // 使用示例 uint8_t alarm_val; ACTIVE_ALARM_BITS(ALARM_1, alarm_val);
用do { ... } while(0)是为了保证宏在任何地方展开都不会出语法问题,但这种方式不如前两种灵活,一般不推荐。
内容的提问来源于stack exchange,提问作者jabroni
相关产品推荐
相关产品推荐

