2024年C C++最全嵌入式软件调试常用知识点_嵌入式产品调试相关内容有哪些(1),9次C C++面试经验总结

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

#include <stdio.h>
#include <string.h>

#define LOCAL 

int main()
{
    #ifdef LOCAL
    freopen("datain.txt","r",stdin);
    freopen("dataout.txt","w",stdout);
    #endif

    int num;
    scanf("%d",&num);
    printf("%d",num);
    return 0;
}

重定向部分被写在#ifdef 和#endif ,其含义是:只有定义了符号LOCAL,才编译两条freopen函数。
这种方法适合在竞赛中使用,我们不必每次从输入终端读取特定格式数据,可以将数据写入在datain.txt文件中,使能宏定义,当最后调试完毕后,失能宏定义即可,非常方便!

二、 使用标准预定义宏打印属性

标准C语言预处理要求定义某些对象宏,每个预定义宏的名称一两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程人员重新定义。这里仅仅列举常用的几个:

\_\_LINE\_\_  当前程序行的行号,表示为十进制整型常量
\_\_FILE\_\_  当前源文件名,表示字符串型常量
\_\_DATE\_\_  转换的日历日期,表示为Mmm dd yyyy 形式的字符串常量,Mmm是由asctime产生的。
\_\_TIME\_\_  转换的时间,表示"hh:mm:ss"形式的字符串型常量,是有asctime产生的。(asctime貌似是指的一个函数)

举例:


#include <stdio.h>
#include <string.h>

void why_me()
{
    printf( "This function is %s\n", __func_\_ );
    printf( "The file is %s.\n", __FILE_\_ );
    printf( "This is line %d.\n", __LINE_\_ );
}

int main()
{
    printf( "The file is %s.\n", __FILE_\_ );
    printf( "The date is %s.\n", __DATE_\_ );
    printf( "The time is %s.\n", __TIME_\_ );
    printf( "This is line %d.\n", __LINE_\_ );
    printf( "This function is %s.\n", __func_\_ );

    why_me();

    return 0;
}

大家可以看到这种写法的好处了吧,特别是当被调用函数出错时,我们可以利用这些打印信息很快的定位到出错的位置,方便快速调试。

三、 打印缓冲问题

有时候我们发现我们使用printf()函数打印时,并不能立即打印出我们想要的信息。而是在某个事件触发后(比如换行、缓冲区满等),才打印出我们的信息,这是为什么呢?
原因是printf()函数采用行缓冲机制,减少了I/O时间与磁盘读写时间,提高了系统性能。但是,也带来了问题,就是不能实时打印信息,这里提供几种解决方案解决行缓冲带来的延迟

  • 在printf里添加\n
  • 刷新缓冲区:fflush(stdout);
  • 直接将缓冲区禁掉: setvbuf(stdout,NULL,_IONBF,0);
  • 使用错误标准流,stdout有line buffer: fprintf(stderr,…)
四、 打印开关控制

打印日志虽然能方便快速调试,但是有时也带来了问题,笔者最近也遇到了这种问题。在嵌入式对时序要求较高的场景下,打印非常影响系统的性能。 因此,我们可以使用打印开关,在DEBUG版本时,我们可以打印信息,而在Realease版本时,我们不输出调试信息。
这里利用了一个知识点,C99标准对可变参数宏的支持:__VA_ARGS__
代码:

#include <stdio.h>
#include <string.h>

#define \_\_DEBUG

#ifdef \_\_DEBUG
#define DEBUG(...) printf(\_\_VA\_ARGS\_\_)
#else
#define DEBUG(...)
#endif

int main()
{
    DEBUG("hello %s\n","paopao");
    DEBUG("value %s %d\n","wsq",1000);
    return 0;
}
五、 打印等级控制

有时,我们需要根据当前打印级别进行有选择的调试信息输出,此时就需要对打印进行等级控制。
代码:

#include <stdio.h>
#include <string.h>

#define ERR\_LEVEL 1
#define WARN\_LEVEL 2
#define DEBUG\_LEVEL 3
/\*
 PRINT\_LEVEL setting :
 0: printf off
 1: err log
 2: warning conditions 
 3: debug\_level messages
\*/
#define PRINT\_LEVEL 2

#define ERR(...) \
do{                                 \
    if(PRINT_LEVEL>=ERR_LEVEL)      \
    {                               \
        printf(__VA_ARGS__);        \
    }                               \
}while(0)


#define WARN(...) \
do{                                 \
    if(PRINT_LEVEL>=WARN_LEVEL)     \
    {                               \
        printf(__VA_ARGS__);        \
    }                               \
}while(0)   


#define DEBUG(...) \
do{                                 \
    if(PRINT_LEVEL>=DEBUG_LEVEL)    \


![img](https://img-blog.csdnimg.cn/img_convert/fe83c9724e74dedc21e693799901328b.png)
![img](https://img-blog.csdnimg.cn/img_convert/37878103d4b1e0adf2aaa5269dd1f514.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值