请选择 进入手机版 | 继续访问电脑版
查看: 919|回复: 2

[原创] 宏函数使用注意事项

[复制链接]

该用户从未签到

648

主题

6301

帖子

0

超级版主

Rank: 8Rank: 8

积分
19555
最后登录
2024-3-29
发表于 2021-7-13 10:47:13 | 显示全部楼层 |阅读模式
背景介绍

客户在测试SDK_2_9_1_EVK-MIMXRT1020中的evkmimxrt1020_lwip_tcpecho_freertos工程过程中,想要禁止串口打印功能,通过在Properties->Settings->Preprocessor中设置SDK_DEBUGCONSOLE=2(如图1所示)后重新编译工程,出现了如下图所示的编译错误。

c99e2d16-cb10-42d3-a49d-1120099600d8.png

图 1

1ff111cb-0d09-43a3-ab8d-5709c7727a55.png

图 2

问题分析

在设置SDK_DEBUGCONSOLE=2后选择如下所示的串口打印、输入函数,do-while语句特点是先执行语句后判断条件,当设置while(0)时,表示while 条件永不成立,do后面语句块中的代码只会被执行一次,宏定义代码通过do { /* ... */ } while(0)将要执行的代码块包裹后,可以使得宏定义不会受到大括号、分号等的影响,总是会按你期望的方式调用运行,这是Linux内核代码中常用的宏函数定义方式。

  1. #define PRINTF(...) \
  2.     do              \
  3.     {               \
  4.     } while (0)
  5. #define SCANF(...) \
  6.     do             \
  7.     {              \
  8.     } while (0)
  9. #define PUTCHAR(...) \
  10.     do               \
  11.     {                \
  12.     } while (0)
复制代码

接着,我们根据错误信息定位出产生错误的代码行在fsl_assert.c中的__assertion_failed(char *failedExpr)函数(如下图所示),

87e8fc09-16e4-4ed5-a793-6a82c4f0b45d.png

经过预编译后,__assertion_failed(char *failedExpr)函数为如下所示。

  1. void __assertion_failed(char *failedExpr)
  2. {
  3.     (void)do { } while (0);

  4.     for (;;)
  5.     {
  6.         ;
  7.     }
  8. }
复制代码

到这里,我们应该猜到错误的原因了,就是在do前面加了**(void)**的关键字,既然找出了原因,该如何优雅的消除错误呢?

推荐的方式是修改宏函数而不是__assertion_failed(char *failedExpr)函数,这样可以避免头疼医头,脚痛医脚,而且也不容易给驱动代码带来额外的风险,修改后的代码如下所示。

  1. //#define PRINTF(...) \
  2. // do \
  3. // { \
  4. // } while (0)
  5. //#define SCANF(...) \
  6. // do \
  7. // { \
  8. // } while (0)
  9. //#define PUTCHAR(...) \
  10. // do \
  11. // { \
  12. // } while (0)
  13. #define PRINTF
  14. #define SCANF
  15. #define PUTCHAR
复制代码



回复

使用道具 举报

  • TA的每日心情
    开心
    6 天前
  • 签到天数: 1334 天

    [LV.10]以坛为家III

    88

    主题

    4290

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    9022
    最后登录
    2024-3-29
    发表于 2021-7-13 15:08:18 | 显示全部楼层
    修改后代码在预编译后成了下面所示“

    (void)("ASSERT_ERROR \" %s \n", failedExpr);

    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2023-8-30 17:43
  • 签到天数: 306 天

    [LV.8]以坛为家I

    14

    主题

    1746

    帖子

    4

    金牌会员

    Rank: 6Rank: 6

    积分
    2507
    最后登录
    2023-8-30
    发表于 2021-7-14 10:08:35 | 显示全部楼层
    “Linux内核代码中常用的宏函数定义方式”的讲解内容挺丰富的,学到了!
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-3-29 18:05 , Processed in 0.111718 second(s), 22 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表