0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

可变参数的宏__ VA_ARGS__的用法

黄工的嵌入式技术圈 来源:黄工的嵌入式技术圈 2020-03-20 09:26 次阅读

回顾

在【ANSIC几种特殊的标准定义】中我们讲述了比较常用的几项:

__FILE__:正在编译文件的路径及文件名

__LINE__:正在编译文件的行号

__DATE__:编译时刻的日期字符串 如“Jun 17 2017”

__TIME__:编译时刻的时间字符串 如”1000“

代码:

char BuildFile[] = __FILE__;

int BuildLine = __LINE__;

char BuildDate[] = __DATE__;

char BuildTime[] = __TIME__;

printf("编译文件路径:%s ", BuildFile);

printf("编译代码所在行:%d ", TestLine);

printf("编译日期:%s ", BuildDate);

printf("编译时间:%s ", BuildTime);

提示:__LINE__是整型数据;

其实除了这些还有很多相关的定义,比如:

1.__FUNCTION__:函数名,类型为:字符常量指针。

char const* BuildFunName = __FUNCTION__;

printf("函数名称为:%s ", BuildFunName);

2.__VER__:IDE版本信息,类型为:整型。

如我用的IAR版本为:7.80.04,如下图:

代码:

intIDEVersion = __VER__;

printf("IDE版本:%d ", IDEVersion);

输出:

IDE版本:7080004

更多相关内容,可以自己学会着摸索。而本文讲的内容也是和打印相关,一般都会结合到上面内容一起来使用,详情请看下文。

Ⅰ本文要点--可变参数

我们在学习C语言的时候,都知道printf是可变参数的函数:

char a = 1;

char b = 2;

char c = 3;

printf("a = %d ", a);

printf("a = %d; b = %d ", a, b);

printf("a = %d; b = %d; c = %d ", a, b, c);

上面就是可变参数printf的例子,也就是说参数可以一个也可以多个。而本文说的__VA_ARGS__,就是一个可变参数宏,与printf中可变参数的宏定义一个道理,是新C99规范中增加的。

Ⅱ__VA_ARGS__详情内容

1.关于__VA_ARGS__

__VA_ARGS__它是一个可变参数的宏,就是将左边宏中“...” 的内容原样抄写在右边 __VA_ARGS__ 所在的位置。

要注意的是,printf 的输出格式是括号内左边是字符串,右边是变量,而且右变量与左输出格式是一一对应的,不对应就会出错。可以参看下面那个例子, __VA_ARGS__其实是遵循了printf的格式。

...缺省号代表一个可以变化的参数表。使用保留名 __VA_ARGS__ 把参数传递给宏。当宏的调用展开时,实际的参数就传递给 printf()了。

2.实例说明

#defineSENSOR_Printf(...) printf("--SENSOR--"__VA_ARGS__)

intTemperatureVal = 25;

SENSOR_Printf("温度 = %d℃ ", TemperatureVal);

输出结果:

--SENSOR--温度 = 25℃

用心的朋友可能会猜测的到:“...”类似等于“__VA_ARGS__”。

从例子中我们可以看得出来,__VA_ARGS__的用途,主要是用于可变参数的函数。我们使用较多的printf就是最常见的一个。

如果我们的工程很庞大,我们就可以将打印信息分类,这样的好处就是方便我们识别各类打印信息。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7528

    浏览量

    128401
  • 编译
    +关注

    关注

    0

    文章

    614

    浏览量

    32374
  • Printf
    +关注

    关注

    0

    文章

    79

    浏览量

    13478
收藏 人收藏

    评论

    相关推荐

    printf在keil5的AC6编译器下运行进入死循环的原因?

    是: #defineLCD_UsrLog(...) do { LCD_LineColor = LCD_LOG_TEXT_COLOR; printf(__VA_ARGS__); } while (0) 向大侠们请教怎么解决?
    发表于 04-07 06:46

    STM32U575VGT6 standard request mode配置之后用不了是怎么回事?

    ( huart5, (uint8_t )ch1, sprintf((char )ch1,__VA_ARGS__)); printf_dma("DMA_RIGHTn"); 运行后hard fault error。 求助!
    发表于 03-12 06:19

    C语言-#和##的具体用法

    C语言中,在宏里面使用’#’和’##’有它非常神奇的作用。在宏定义的替换的过程中,#号可以作为一个预处理运算符,把宏参数转换为字符串。##运算符则可以把两个宏参数组合在一起。下面就来说说具体的用法
    的头像 发表于 12-19 12:54 826次阅读
    C语言-#和##的具体<b class='flag-5'>用法</b>

    pcb插针的用法

    pcb插针的用法
    的头像 发表于 12-13 16:58 677次阅读

    oracle中substr函数用法

    中提取子字符串的源字符串,start_position是子字符串的起始位置,length是要提取的子字符串的长度(可选参数)。 下面将详细介绍SUBSTR函数的用法及示例。 基本用法 最简单的
    的头像 发表于 12-05 16:57 480次阅读

    python中tuple的用法

    使用逗号进行分隔。元组在Python中具有许多有用的特性和用法,本文将详尽、详实、细致地介绍Python中元组的全部内容。 首先,元组可以用来存储多个值。与列表不同的是,元组一旦创建就不能被修改,这意味着元组的元素是不可变的。虽然元组的元素不
    的头像 发表于 11-21 16:27 515次阅读

    如何才能在51系统下使用类似printf这样的可变参数的子函数呢?

    学习自己构造可变参数的子函数使用“...”,做参数。知道是用堆栈传递函数的,但是在keil中仿真怎么都不行。用sizeof(*p)发现51单片机中指针变量的长度竟然是3字节,每次执行p++会让地址
    发表于 10-30 08:27

    怎么设计c语言的可变参数函数?

    怎么设计c语言的可变参数函数
    发表于 10-27 07:10

    在Linux上time基础用法详解

    1 基础用法详解 先来看下最基础的用法,也可能是大家最常见的用法了 root @chopin : ~ $ time find . - name "chopin.txt"...... real
    的头像 发表于 10-09 17:28 497次阅读

    java 8的日期用法

    = LocalDate.now(); System.out.println(now);} 设置日期 of 方法是一个静态方法,接收年、月、日三个 int 参数,返回 LocalDate 对象。需要注意的是月份不是从 0 开始的。 public static void main ( String []
    的头像 发表于 10-09 15:50 227次阅读

    Linux内核pr_xx()函数封装

    pr_emerg (fmt, ...) printk (KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) #define pr_alert (fmt
    的头像 发表于 09-27 15:58 367次阅读

    Stream模块的基础用法和进阶用法

    有用。在本教程中,我们将介绍 Stream 模块的基础用法和进阶用法,并提供示例。 基础用法 在本节中,我们将介绍 Stream 模块的基础用法,并提供基础示例。 从 Vec 中创建
    的头像 发表于 09-19 15:33 705次阅读

    SQLx的基础用法和进阶用法

    SQLx是一个Rust语言的异步SQL数据库访问库,支持多种数据库,包括PostgreSQL、MySQL、SQLite等。本教程将以SQLite为例,介绍SQLx的基础用法和进阶用法。 基础用法
    的头像 发表于 09-19 14:29 1238次阅读

    关于NUC972 VA_FBCTRL寄存器配置问题

    对于参数资料里面描述的VA_FF[26:16] VA_FF和VA_STRIDE[10:0]里面的描述不是很明白,请指教 看到DEMO程序里面会设置为分辨率的一半,比如480*272的配
    发表于 09-04 06:58

    如何为Serial.printf() 编写一个简单的包装函数?

    , ...) { if (DEBUG_MODE) { va_list args; va_start(args, format); Serial.printf(format,
    发表于 05-04 07:24