经典C语句:#define reg_write32(addr, val) do { (*((volatile uint32_t *)(addr)) = (uint32_t)(val)); } while(0)
#define reg_write32(addr, val) do { \
    (*((volatile uint32_t *)(addr)) = (uint32_t)(val)); \
} while(0)
这种do { ... } while(0)的宏定义写法是为了解决C语言宏的多个常见问题,主要有以下几个优点:
1. 避免分号问题
问题示例:
// 不好的写法
#define reg_write32(addr, val) (*((volatile uint32_t *)(addr)) = (uint32_t)(val))
if (condition)
    reg_write32(addr, val);  // 展开后会有语法问题
else
    // 其他代码
展开后:
if (condition)
    (*((volatile uint32_t *)(addr)) = (uint32_t)(val));;
else
    // 其他代码
注意有两个分号,这在if语句中会导致问题。
2. 避免与else的匹配问题
问题示例:
// 使用大括号的写法也有问题
#define reg_write32(addr, val) { (*((volatile uint32_t *)(addr)) = (uint32_t)(val)); }
if (condition)
    reg_write32(addr, val);
else
    // 其他代码
展开后:
if (condition)
    { (*((volatile uint32_t *)(addr)) = (uint32_t)(val)); };
else
    // 其他代码
大括号后的分号会导致else无法匹配前面的if。
3. do { ... } while(0)的优势
正确展开:
if (condition)
    do { (*((volatile uint32_t *)(addr)) = (uint32_t)(val)); } while(0);
else
    // 其他代码
这种写法的好处:
- 必须加分号:
while(0)后面的分号是必须的 - 构成完整语句:在语法上是一个完整的语句
 - 兼容各种上下文:可以在
if/else、循环等任何地方安全使用 
4. 其他宏问题的避免
这个宏还通过其他方式避免了常见问题:
#define reg_write32(addr, val) do { \
    (*((volatile uint32_t *)(addr)) = (uint32_t)(val)); \
} while(0)
// 避免参数多次求值:每个参数只使用一次
// 使用括号:确保运算优先级
// volatile:防止编译器优化
5. 使用示例
// 各种使用场景都能正常工作
reg_write32(REG_ADDR, 0x1234);
if (condition)
    reg_write32(REG_ADDR, value);
for (int i = 0; i < 10; i++)
    reg_write32(addr_array[i], values[i]);
这种写法是C语言中编写复杂宏的标准最佳实践。
                    
                
                
            
        
浙公网安备 33010602011771号