打印
[其它应用]

不清不楚之C语言中##__VA_ARGS__与__VA_ARGS__

[复制链接]
1785|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
probedog|  楼主 | 2024-11-26 15:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在开发过程中又玩起了C语言的可变参数,在资源受限的MCU平台上,一般不太建议使用可变参数或者相应标准库函数如printf等,以免编译进去后导致程序代码段瞬间变大很多,当然有些简化版本的lib,不过也相当废资源,不过现在MCU的性能越来越卷,大部分项目都是资源过剩。不过话说回来,C语言的可变参数用起来还挺顺手,像嵌入式经常打印的日志,为了更好的可移植性通常会进行封装,今天就不再赘述可变参数的语法了,大家感兴趣可以翻阅公众号往期文章,今天bug菌仅聊聊##__VA_ARGS__与__VA_ARGS__这对可变参数宏,相信大家在日常的编程中接触得倒不多,不过在大型开源软件中还是屡有见到,那么下面带大家分析分析:1__VA_ARGS__介绍__VA_ARGS__ 是C语言中的一个预定义宏,用于处理可变数量的参数列表。通常用在宏定义中,以便宏能够接受不定数量的参数,并将它们作为整体处理。在C语言中,使用函数可以接受可变数量的参数,例如printf和fprintf。然而,在宏定义中,参数数量通常是固定的。为了能够定义可以处理不同数量参数的宏,C99标准引入了__VA_ARGS__。下面的例子也都是在C99标准下编译运行。__VA_ARGS__表示所有在宏调用中传递的额外参数。它可以放在宏定义的参数列表的末尾,用于接收任意数量的额外参数,比如:#define DEBUG_LOG(fmt, ...) printf(fmt, __VA_ARGS__)
解析:DEBUG_LOG 是一个宏,接受至少一个参数 fmt(格式化字符串),后面可以是任意数量的参数。__VA_ARGS__ 表示可变参数列表,在宏展开时会被替换为传递给 DEBUG_LOG 宏的所有实际参数。示例:#define DEBUG_LOG(fmt, ...) \
    printf("[%s:%d] " fmt "\n", __FILE__, __LINE__, __VA_ARGS__)


DEBUG_LOG("Hello, %s! The answer is %d\n", "world", 42);
在这个调用中,"Hello, %s! The answer is %d\n" 是格式化字符串fmt,"world" 和 42 是额外的参数。这些参数会被依次传递给 printf 函数。__VA_ARGS__ 必须总是与宏定义中的省略号 ... 一起使用。省略号...用于指示宏可以接受可变数量的参数。在宏定义中,__VA_ARGS__ 可以单独使用(如果没有额外参数时),也可以与其他参数一起使用。2##在前面有啥用?大家在了解__VA_ARGS__时,一定会看到有些地方在该宏定义前使用 ## 运算符来处理可变参数,如:#define DEBUG_LOG(fmt, ...) \
    printf("[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
其中这里的##运算符主要是用于连接左侧的符号(通常是逗号)和右侧的参数,从而确保宏展开时语法正确。对于如下使用可变参数:
 DEBUG_LOG("Value of x: %d", 42);
__VA_ARGS__与##__VA_ARGS__是没有太大区别的,且都能编译通过,打印输出相同的结果。然而当可变参数为空时,如下:DEBUG_LOG("Program starting...");
在C99编译器下,无##修饰的宏定义DEBUG_LOG 则会编译失败,而存在##修饰的宏##__VA_ARGS__ 处理为空的可变参数列表,防止在宏展开时出现不必要的逗号,从而使得编译通过。

使用特权

评论回复
沙发
中国龙芯CDX| | 2024-11-27 08:38 | 只看该作者
__VA_ARGS__可变参数宏了解一下

使用特权

评论回复
板凳
tpgf| | 2024-12-3 15:35 | 只看该作者
#define PRINT(format, ...) printf(format, __VA_ARGS__)

使用特权

评论回复
地板
renzheshengui| | 2024-12-6 12:59 | 只看该作者
__VA_ARGS__ 是一个预处理器符号,代表传递给宏的可变参数列表。它通常用在宏定义中,以便宏能够接受任意数量的参数

使用特权

评论回复
5
wowu| | 2024-12-6 16:26 | 只看该作者
CW32L010F8P6是基于eFlash的单芯片低功耗微控制器,支持多种工作模式,包括运行模式、休眠模式以及深度休眠模式

使用特权

评论回复
6
xiaoqizi| | 2024-12-6 19:07 | 只看该作者
#__VA_ARGS__常用于需要在预处理阶段生成特定标识符或代码片段的场景

使用特权

评论回复
7
木木guainv| | 2024-12-6 20:56 | 只看该作者
__VA_ARGS__ 用于传递可变参数,而 [size=0.875]##__VA_ARGS__ 用于在预处理阶段进行标记连接操作

使用特权

评论回复
8
磨砂| | 2024-12-6 22:41 | 只看该作者
#define CONCAT(a, b) a##b
#define STRINGIFY(x) #x
#define EXPAND_AND_STRINGIFY(x) STRINGIFY(x)
#define DEBUG_PRINT(...) do { \
    printf("Debug: " EXPAND_AND_STRINGIFY(__VA_ARGS__) "\n"); \
} while (0)

int main() {
    int var = 42;
    DEBUG_PRINT(var);
    return 0;
}


使用特权

评论回复
9
Bowclad| | 2024-12-13 14:44 | 只看该作者
可变参数有什么用啊

使用特权

评论回复
10
OKAKAKO| | 2024-12-22 21:47 | 只看该作者
C语言的可变参数了解一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

387

主题

2097

帖子

3

粉丝