宏的应用【C语言】

一、打印串口信息

代码


#define USART_DEBUG

#ifdef USART_DEBUG
#define user_printf(format, ...)        printf(format"\r\n", ##__VA_ARGS__)
#define user_info(format, ...)          printf(__FILE__"\t[info]:"format"\r\n", ##__VA_ARGS__)
#define user_debug(format, ...)         printf(__FILE__"\t[debug]:"format"\r\n", ##__VA_ARGS__)
#define user_error(format, ...)         printf(__FILE__"\t[error]:"format"\r\n", ##__VA_ARGS__)
#else
#define user_printf(format, ...)
#define user_info(format, ...)
#define user_debug(format, ...)
#define user_error(format, ...)
#endif

使用


通过开发板每500ms通过串口打印以下信息

user_printf("user_printf %d", i++);
user_info("user_info %d", i);
user_debug("user_debug %d", i);
user_error("user_error %d", i);

在这里插入图片描述

通过打印结果可知与普通的printf相比,有以下优点:
    1)自动换行
    2)显示文件路径
    3)通过对齐使打印信息更整洁
    4)不需要打印信息时,只需要注释掉#define USART_DEBUG

理解


制表符 \t 的作用

  • 排版对齐
    \t 通常用于格式化输出,帮助将文本或数据对齐,例如输出表格或列数据时,它可以让数据更加整齐
#include <stdio.h>

int main(void)
{
	printf("aaa\tTest\r\n");
	printf("aaaaa\tTest\r\n");
	return 0;
}
  • 跳到下一个制表位置
    制表符让你能够快速将光标移动到一个固定的列位置,这样你就不需要手动计算空格数

可变参数宏

在GNU C中,从C99开始,宏可以接受可变数目的参数,就象可变参数函数一样。和函数一样,宏也用三个点…来表示可变参数

  • __VA_ARGS__
#include <stdio.h>
#define debug(...) printf(__VA_ARGS__)
int main(void)
{
    int year = 2024, month= 11, day= 7;
    
    debug("[%d年%d月%d日]\tThis is a debug test\r\n", year, month, day);
    return 0;
}
  • 可变参数别称
    通过一些语法,你可以给可变参数起一个名字,而不是使用__VA_ARGS__
#include <stdio.h>
#define debug(format, args...) printf(format, args)
int main(void)
{
    int year = 2024, month= 11, day= 7;
    
    debug("[%d年%d月%d日]\tThis is a debug test\r\n", year, month, day);
    return 0;
}
  • 无参传入情况
    与可变参数函数不同的是,可变参数宏中的可变参数必须至少有一个参数传入,不然会报错,为了解决这个问题,需要一个特殊的“##”操作,如果可变参数被忽略或为空,“##”操作将使预处理器(preprocessor)去除掉它前面的那个逗号
#include <stdio.h>
#define debug(format, args...) printf(format, ##args)
int main(void)
{
    debug("This is a debug test\r\n");
    return 0;
}
  • 宏连接符##
    宏定义为:#define XNAME(n) x##n
    代码为:XNAME(4)
    预编译时,宏发现 XNAME(4)XNAME(n) 匹配,则令 n4,然后将右边的 n 的内容也变为 4,然后将整个 XNAME(4) 替换为 x##n,亦即 x4,故最终结果为 XNAME(4) 变为 x4
#include <stdio.h>
#define XNAME(n) x##n
#define PRINT_XN(n) printf("x" #n " = %d\n", x##n);
int main(void)
{
    int XNAME(1) = 14; // becomes int x1 = 14;
    int XNAME(2) = 20; // becomes int x2 = 20;
    PRINT_XN(1);       // becomes printf("x1 = %d\n", x1);
    PRINT_XN(2);       // becomes printf("x2 = %d\n", x2);
    return 0;
}

参考连接:
 
        🫡优快云橘长_

        🫡优快云乌托

二、简化代码(单片机)

代码


通过设置单片机 PB7 引脚的高低电平来控制 LED 的亮灭

#define LED0_GPIO_PORT                  GPIOB
#define LED0_GPIO_PIN                   GPIO_PIN_7

#define LED0(x)   do{ x ? \
                      HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_SET) : \
                      HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_RESET); \
                  }while(0)      /* LED0翻转 */

使用


配置好 LED 控制引脚,并将上述宏定义写在 LED 驱动头文件后,在 main 函数的 while 循环中执行以下代码可实现亮、灭

LED0(1);
delay_ms(500);
LED0(0);
delay_ms(500);

上面的宏有什么作用?
    1)前两个宏可以使我们更加方便的更换 LED 的控制引脚
    2)第3个宏可以使我们用更加简洁、易懂的代码去控制 LED 亮灭

理解


  • 预处理时,LED0(1) 会替换成 do{...}while,1 会替换掉 x
  • 通过三目运算符(表达式1 ? 表达式2 : 表达式3)来判断执行那个表达式
  • \ 可以给代码换行,更易观察
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值