do{}while(0)宏定义方式广泛应用于Linux内核源码、FreeRTOS、uCOS-II、ARM内核、STM32......。

主要基于以下技术原因和优势:


场景1:语法歧义或错误、逻辑错误问题

#define EXTIE1()     {EXTI_FTSR &= 0xFF00; EXTI_BTSR &= 0xFF0F;}
#define EXTIE2()     {EXTI_FTSR &= 0xFF00; EXTI_BTSR &= 0xFF0F}
#define EXTIE3()      EXTI_FTSR &= 0xFF00; EXTI_BTSR &= 0xFF0F

if (condition)
    EXTIE1(x); // 这里多个分号
if else
    EXTIE2(); // 这里有分号
if else
    EXTIE3(); // 这里有分号
else
    Something(); // 这里有分号

展开

if (condition)
    {EXTI_FTSR &= 0xFF00; EXTI_BTSR &= 0xFF0F;}; // 这里有两个分号!语法歧义或错误
if else
    {EXTI_FTSR &= 0xFF00; EXTI_BTSR &= 0xFF0F}; // 这里有个分号!语法歧义或错误
if else
    EXTI_FTSR &= 0xFF00; 
    EXTI_BTSR &= 0xFF0F; // 逻辑错误
else
    Something(); // 这里有分号


场景2:编码风格不一致导致的维护问题

#define EXTIE1()     {EXTI_FTSR &= 0xFF00; EXTI_BTSR &= 0xFF0F;}
#define EXTIE2()      EXTI_FTSR &= 0xFF00;
#define EXTIE3()      EXTI_BTSR &= 0xFF0F
if (condition)
    EXTIE1(x) // 这里无分号!与函数语法不一致
if else
    EXTIE2() // 这里有个分号!
if else
    EXTIE3(); // 这里有个分号!若这个宏是其他合作者定义的,与团队语法不一致
else
    Something(); // 这里有分号

展开

if (condition)
    {EXTI_FTSR &= 0xFF00; EXTI_BTSR &= 0xFF0F;} // 这里无分号!
if else
    EXTI_FTSR &= 0xFF00; // 这里有个分号!
if else
    EXTI_BTSR &= 0xFF0F; // 这里有个分号!
else
    Something(); // 这里有分号

场景3:支持局部变量定义‌

#define SWAP(a, b) {tmp = a, a = b, b = tmp;} // 有语法错误,除非tmp在外面定义变量
#define SWAP(a, b) do{int tmp = a, a = b, b = tmp;}while(0) // 正确,不用单独在外部定义临时变量

场景4:避免空宏的编译警告‌

#define MACRO_DEF1()   // 空宏定义可能引发编译器警告
#define MACRO_DEF2() do{}while(0) // 空宏定义能通过编译,无警告

场景5: 行为一致,不产生额外代码

优化友好:现代编译器会优化掉 while(0),不会产生任何额外代码
作用域清晰:在宏内部定义的变量不会泄露到外部
行业标准:被广泛认可的最佳实践,无论在哪里使用,行为都是一致的

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐