C语言基础:do{...}while(0)的使用,很秀

发布于 2023-11-17 10:56
浏览
0收藏

工程开发中,尤其阅读代码时,有时会碰到一些让我们内心"嗯哼"一下的代码。比如:

#define Call_Mcal_DmaMux_Init(u32ptr) \
do \
{ \
Mcal_Trusted_Call1param(Mcl_DmaMux_Init,(u32ptr)); \
} \
while(0)

如上的宏定义,是否能理解?本文,我们就聊聊宏定义与do{...}while(0)的结合。

1、宏的使用

开发中,宏的使用很频繁。为了精简代码的编写过程,有时,我们会将多条语句用一个宏表示。


示例 1:

#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL()  do { \
  if (tcpip_try_callback(pbuf_free_ooseq_callback, NULL) != ERR_OK) { \
      SYS_ARCH_PROTECT(old_level); \
      pbuf_free_ooseq_pending = 0; \
      SYS_ARCH_UNPROTECT(old_level); \
  } } while(0)

示例 2:

#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \
    if (IP_IS_ANY_TYPE_VAL(*ipaddr) || IP_IS_V6_VAL(*ipaddr)) { \
      IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \
    } else { \
      IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \
    } } while(0)

熟悉Lwip(Light Weight (轻型)IP协议)的小伙伴,应该比较熟悉上述两个示例。在Lwip中,会经常看到宏定义do{...}while(0)的结构。如上示例可以看出,使用宏替换多条语句,会方便的多。但是,为什么要使用do{...}while(0)这样的结构形式呢?答:使用do{...}while(0)构造后的宏定义,可避免大括号、分号等的影响。有点难以理解是吗?看一个例子消化一下。


(一)不用do{...}while(0)结构进行宏定义带来的影响


示例:定义宏Get_OptResult(a, b, c, d)精简代码c = ((a) + (b));和d = ((a) * (b));,如下所示:

#include <stdio.h>

#define Get_OptResult(a, b, c, d) \           
         c = ((a) + (b)); \
         d = ((a) * (b));                             

int main(void)
{
  int JudgeFlag = 0;
  int cResult, dResult;
  
  if(JudgeFlag == 0)
      Get_OptResult(60, 20, cResult, dResult);
  else
  {
    cResult = 100;
    dResult = 1000;
  }

    printf("cResult = %ld, dResult = %ld.\n", cResult,dResult );

    getchar();
}

如上代码有什么问题呢?宏展开以后,如下所示:

#include <stdio.h>

#define Get_OptResult(a, b, c, d) \           
         c = ((a) + (b)); \
         d = ((a) * (b));                             

int main(void)
{
  int JudgeFlag = 0;
  int cResult, dResult;
  
  if(JudgeFlag == 0)
         c = ((a) + (b));
         d = ((a) * (b));;
  else
  {
    cResult = 100;
    dResult = 1000;
  }

    printf("cResult = %ld, dResult = %ld.\n", cResult,dResult );

    getchar();
}

在Line14处,分号";"这将会带来什么影响呢?答:else语句永远不会被执行,此时,else没有对应的if,编译器可能会报语法错误,如下所示:

C语言基础:do{...}while(0)的使用,很秀 -汽车开发者社区

面对这个问题,怎么办呢?答:使用do{...}while(0),吸收分号";"带来的影响。


(二)使用do{...}while(0)结构进行宏定义

#include <stdio.h>

#define Get_OptResult(a,b,c,d) do {\           
         c = ((a) + (b)); \
         d = ((a) * (b)); \
         }while(0)

int main(void)
{
  int JudgeFlag = 0;
  int cResult, dResult;
  
  if(JudgeFlag == 0)
      Get_OptResult(60, 20, cResult, dResult);
  else
  {
    cResult = 100;
    dResult = 1000;
  }

    printf("cResult = %ld, dResult = %ld.\n", cResult,dResult );

    getchar();
}

宏展开,如下所示:

#include <stdio.h>

#define Get_OptResult(a,b,c,d) do {\           
         c = ((a) + (b)); \
         d = ((a) * (b)); \
         }while(0)

int main(void)
{
  int JudgeFlag = 0;
  int cResult, dResult;
  
  if(JudgeFlag == 0)
    do{
         c = ((a) + (b));
         d = ((a) * (b));
    }while(0);
  else
  {
    cResult = 100;
    dResult = 1000;
  }

    printf("cResult = %ld, dResult = %ld.\n", cResult,dResult );

    getchar();
}

如上,使用do{...}while(0)结构,宏展开以后,吸收了分号";"带来的影响,进而确保else语句可以被执行到。

综上,在使用宏定义多条语句时,do{...}while(0)结构不妨一试。


文章转载自公众号:开心果 Need Car

分类
收藏
回复
举报
回复
相关推荐