C语言中能否用可变参数宏实现独热编码归约操作?
实现编译期计算的可变参数ONE_HOT宏(C语言)
这个问题和旧问题《Variadic recursive preprocessor macros - is it possible?》类似,但考虑到C语言的发展,重新提出:希望实现一个编译期计算的常量ONE_HOT独热编码操作,将枚举元素的独热编码结果存入uint32_t,即把ONE_HOT(a,b,c,...)的所有参数归约为(1<<a)|(1<<b)|(1<<c)...的形式。
已有的两种实现方案
方案A:计算时对每个条目进行位偏移
typedef enum { FIRST, SECOND, THIRD, // 更多枚举项 MY_ENUM_NUM_ENTRIES // 设计上保证其值不超过sizeof(uint32_t)*8 } MY_ENUM_TYPE; // 示例:仅FIRST和THIRD被"置位" uint32_t expected_entries = (1<<FIRST) | (1<<THIRD); // 检查某一位是否置位 if(expected_entries & (1<<SECOND)){ // 执行操作 }
该方案无需修改枚举定义,但每次操作都要手动编写1<<,代码略显繁琐。
方案B:修改enum声明,为其分配2的幂值
typedef enum { FIRST = (1 << 0), SECOND = (1 << 1), THIRD = (1 << 2), // 更多枚举项 MY_ENUM_NUM_ENTRIES // 缺点:这个值现在失效了,需要额外处理 } MY_ENUM_TYPE; // 优点:独热编码操作更易读易写 uint32_t expected_entries = FIRST | THIRD; // 检查某一位是否置位 if(expected_entries & SECOND){ // 执行操作 }
该方案简化了编码操作,但破坏了原枚举中MY_ENUM_NUM_ENTRIES的语义,需要额外的 workaround。
需求的方案C:可变参数宏实现
希望通过可变参数宏实现ONE_HOT操作,满足以下要求:
- 避免使用不推荐的递归宏定义;
- 避免为每个参数数量单独定义多达32个宏;
- 尽可能在编译期完成独热编码计算;
- 无需修改原枚举定义。
以下是期望效果的伪代码:
#define IS_HOT(encoded, bit) (encoded & (1<<bit)) #define SET_HOT(encoded, bit) (encoded | (1<<bit)) #define CLEAR_HOT(encoded, bit) (encoded & (0xFFFFu^(1<<bit))) // 伪代码:希望ONE_HOT接收的所有参数a,b,c...都被移位后按位或,生成独热编码 #define ONE_HOT(a, b, c, ...) (1 << a) | (1 << b) | (1 << c) | ONE_HOT(##__VA_ARGS__) // 伪代码结束 typedef enum { FIRST, SECOND, THIRD, // 更多枚举项 MY_ENUM_NUM_ENTRIES // 设计上保证其值不超过sizeof(uint32_t)*8 // 额外好处:无需重新定义原枚举 } MY_ENUM_TYPE; // 期望的简洁写法 uint32_t expected_entries = ONE_HOT(FIRST, THIRD); // 而非这种繁琐的嵌套写法 // uint32_t expected_entries = SET_HOT(SET_HOT(0, FIRST), THIRD); // 检查置位情况 if(IS_HOT(expected_entries, SECOND)){ // 执行操作 }
内容的提问来源于stack exchange,提问作者AlejandroLIF
相关产品推荐
相关产品推荐

