va_start 与 va_end

embedded/2024/9/23 9:26:12/

在C语言中,当我们定义一个可变参数的函数时,我们需要一种方法来依次访问每个参数。va_startva_end宏就是用来处理这些可变参数的。

va_start宏的作用是初始化一个va_list类型的变量,这个变量是用来存储和访问可变参数的。va_start应该在函数中对其它参数做任何处理之前调用。要使用va_start宏,你需要两个参数:首先是你定义的va_list类型变量,其次是函数的最后一个非可变参数。你可以把它理解为告诉va_list变量从哪里开始获取可变参数列表。

下面是va_start宏的一个示例:

#include <stdarg.h>// 假设format是最后一个非可变参数
va_list args;
va_start(args, format);

当你完成了可变参数的处理,并且不再需要va_list类型变量后,你应该使用va_end宏。va_end宏的作用是清理赋予va_list变量的任何资源。虽然在很多实现中,va_end可能仅仅是一个空操作,但它的使用是标准要求的好习惯,可以保证代码的可移植性。

va_end宏是这样使用的:

va_end(args);

它需要va_list类型变量作为参数,并且应该与每一个va_start宏的调用相匹配。

在可变参数的函数中,format并不是一个特定的变量名,它一般代表函数中最后一个固定的参数,用来告诉va_start宏从哪个参数之后开始处理可变参数列表。

理解这个概念可能需要看一个例子。假设我们有一个函数print_formatted,它的第一个参数是一个格式字符串(类似于printf函数中的格式字符串),后面可以跟任意多的参数。这个格式字符串就是我们所说的“最后一个非可变参数”。

例如:

void print_formatted(const char *format, ...) {va_list args;va_start(args, format); // 这里,format 是最后一个固定参数// ...va_end(args);
}

在这个例子中,format的角色就是告诉va_start:可变参数开始于format参数之后,因为format是在省略号...之前定义的最后一个参数。这样,当我们在函数内部使用va_list遍历参数时,它会跳过format,从紧随其后的第一个可变参数开始处理。

简而言之,format就是函数签名中,紧邻可变参数省略号...左边的那个参数。这个“格式参数”只是一个占位符,它在不同函数中可以有不同的名字,关键在于它是可变参数之前的最后一个参数。

void dump(void* buf_src, int len, const char *format, ...)
{if (buf_src == NULL || len <= 0){return;}va_list args, args_copy;va_start(args, format);va_copy(args_copy, args);int required_len = vsnprintf(NULL, 0, format, args) + 1;va_end(args);char *str_buf = (char *)malloc(required_len);if (str_buf == NULL){va_end(args_copy);return;}vsnprintf(str_buf, required_len, format, args_copy);va_end(args_copy);char *data_buf = (char *)malloc(len * 3);if (data_buf == NULL){free(str_buf);return;}unsigned char *byte_src = (unsigned char *)buf_src;for (int i = 0; i < len; i++) {snprintf(&data_buf[3 * i], 4, "%02X ", byte_src[i]);}data_buf[len * 3 - 1] = '\0';printf("%s:%s\n", str_buf, data_buf);free(str_buf);free(data_buf);
}

 


http://www.ppmy.cn/embedded/25520.html

相关文章

数据结构-树和森林之间的转化

从树的二叉链表的定义可知&#xff0c;任何一棵和树对应的二叉树&#xff0c;其根节点的右子树必为空。这里我们举三个树&#xff0c;将这个由三个树组成的森林组成二叉树是这个样子的。 下面我们说明一下详细过程&#xff0c;首先将每个树转化为二叉的状态&#xff0c;如图所示…

linux jmeter ant下载并安装【2024-亲测】

环境 centos7 一、下载jmeter 在这里插入代码片wget https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.6.3.tgz --no-check-certificate解压 tar -zxvf apache-jmeter-5.6.3.tgz复制到安装目录、设置环境变量 vim /etc/profile添加环境变量&#xff0c;路径改成…

数据结构_时间复杂度

✨✨所属专栏&#xff1a;数据结构✨✨ ✨✨作者主页&#xff1a;嶔某✨✨ 什么是时间复杂度&#xff1f; 时间复杂度的定义&#xff1a;在计算机科学中&#xff0c;算法的时间复杂度是一个函数&#xff0c;它定量描述了该算法的运行时间。一个算法执行所耗费的时间&#xff0…

Python来计算 1,2,3,4 能组成多少个不相同且不重复的三位数?

我们今天的例子是 有 1&#xff0c;2&#xff0c;3&#xff0c;4 四个数字&#xff0c;它们能组成多省个互不相同且无重复的三位数&#xff1f;都分别是多少&#xff1f; 话不多说&#xff0c;我们先上代码 num 0 # 我们写了三个for循环&#xff0c;表示生成的三位数 for i…

VM Ubuntu unknown filesystem

unknown filesystem Entering rescue mode... grub rescue> Ubuntu中遇到“error: unknown filesystem”和“Entering rescue mode... grub rescue>”的错误提示时&#xff0c;通常表示GRUB&#xff08;GRand Unified Bootloader&#xff09;无法识别或加载文件系统。这…

GateWay具体的使用!!!

一、全局Token过滤器 在Spring Cloud Gateway中&#xff0c;实现全局过滤器的目的是对所有进入系统的请求或响应进行统一处理&#xff0c;比如添加日志、鉴权等。下面是如何创建一个全局过滤器的基本步骤&#xff1a; 步骤1: 创建过滤器类 首先&#xff0c;你需要创建一个实现…

记录一些容易遗忘的东西

文章目录 native、sync 修饰符this.$nextTick native、sync 修饰符 native &#xff1a;在对子组件使用 click 的时候若不使用该修饰符&#xff0c;那么就不能执行点击事件&#xff0c;会被判断为子向父组件传的值sync &#xff1a; 类似于 v-model 的响应式修饰符&#xff0c…

day06 51单片机-点阵led

1 点阵LED 1.1 需求描述 本案例介绍如何使用点阵LED显示一排由左上到右下的斜线。 1.2 硬件设计 1.2.1 硬件原理图 点阵内部的原理图: 点阵LED的原理也非常简单,就是LED点灯。例如,我们想要让13列(阳极端)9行(阴极端)的LED点亮,需要13为高电平,9为低电平。注意对于…