【发布时间】:2022-11-02 17:14:49
【问题描述】:
可以在 C 宏中赋值(即在宏中有左值)吗?例如,我想根据指定的位位置将一个数字的位设置为1。这样做可以吗:
#define SET_BIT(data, pos) ((data) |= (1U << (pos)))
我已经对此进行了测试并且它有效,但我觉得我在这里如履薄冰,如果我习惯了这样的宏,我最终会遇到问题。
【问题讨论】:
可以在 C 宏中赋值(即在宏中有左值)吗?例如,我想根据指定的位位置将一个数字的位设置为1。这样做可以吗:
#define SET_BIT(data, pos) ((data) |= (1U << (pos)))
我已经对此进行了测试并且它有效,但我觉得我在这里如履薄冰,如果我习惯了这样的宏,我最终会遇到问题。
【问题讨论】:
一旦预处理器在代码中完成了宏的扩展,宏将不存在。如果你有这样的声明
SET_BIT(some_data, some_pos);
然后它将被替换为
((some_data) |= (1U << (some_pos)));
在被解析和编译的代码中。
简而言之,在宏中进行赋值是非常好的。
第一个SET_BIT_TO_VAL 宏的问题:
#define SET_BIT_TO_VAL(data, pos, val) (CLEAR_BIT(data, pos); (data) |= (1U << (pos)))
是您将语句放在括号内,就像它们是表达式一样。所以这不会建立。
在宏中对语句进行分组的常用方法是将它们包装在 do { ... } while(0) 循环中:
#define SET_BIT_TO_VAL(data, pos, val)
do {
CLEAR_BIT(data, pos);
SET_BIT(data, pos);
} while (0)
【讨论】:
#define CLEAR_BIT(data, pos) ((data) &= ~(1U << (pos))),并且想要清除位,然后在另一个宏中设置位,则括号有问题:#define SET_BIT_TO_VAL(data, pos, val) (CLEAR_BIT(data, pos); (data) |= (1U << (pos)))。在这种情况下是否可以将宏放在花括号中,例如:#define SET_BIT_TO_VAL(data, pos, val) {CLEAR_BIT(data, pos); (data) |= (1U << (pos));}?