当前位置: 首页 > news >正文

C++之va_start、vasprintf、va_end应用总结(二百二十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的:C++之va_start、vasprintf、va_end应用总结。

在C/C++语言中,va_startvasprintfva_end是与可变参数相关的函数。它们通常与stdarg.h头文件一起使用。

  1. va_start函数:

    • va_start函数用于初始化可变参数列表。它接受两个参数:第一个参数是一个va_list类型的变量,第二个参数是最后一个固定参数的前一个参数的名称。
    • 这个函数将va_list类型变量初始化为指向可变参数列表的起始位置。
  2. vasprintf函数:

    • vasprintf函数用于将格式化的可变参数输出到动态分配的字符串中。
    • 它接受两个参数:第一个参数是一个指向char指针的指针,第二个参数是一个格式化字符串。
    • 这个函数会根据格式化字符串和可变参数列表生成一个动态分配的字符串,并将指针保存在第一个参数所指向的位置。
  3. va_end函数:

    • va_end函数用于结束可变参数的获取。
    • 它接受一个参数,即一个va_list类型的变量。
    • 这个函数对可变参数列表进行清理,使其无法再被访问。

通常在需要处理可变参数的情况下,使用实现Printf风格的函数或者处理命令行参数时。

2.应用实例

<1>.v1.0

#include <stdio.h>
#include <stdarg.h>void sum(int count, ...)
{va_list args;int total = 0;// 初始化可变参数列表va_start(args, count);// 遍历可变参数列表并求和for (int i = 0; i < count; i++){int num = va_arg(args, int);total += num;}// 结束可变参数列表va_end(args);printf("Sum: %d\n", total);
}int main()
{sum(3, 1, 2, 3);  // 输出 Sum: 6return 0;
}

va_start是一个宏,用于处理可变参数列表。它的原理是基于C语言的可变参数机制。

va_start宏的工作原理如下:

  1. 首先,通过传入的参数列表的类型信息和格式化字符串来确定参数列表的起始位置。

  2. 然后,通过指针运算和类型大小来计算出参数列表中各个参数的位置。

  3. 最后,将参数列表位置信息保存在一个va_list类型的变量中,供后续函数进行处理。

va_start宏的实现通常依赖于编译器和操作系统的底层支持。它使用了一些机制来获取参数列表的信息,如栈帧结构、类型信息、指针运算等。

具体实现的细节可能因编译器和操作系统而异,但通常会涉及以下步骤:

  1. 获取栈帧指针:va_start宏需要通过访问栈来获取参数列表的位置信息。它首先获取当前函数的栈帧指针,可以通过编译器提供的相关函数或底层汇编指令来实现。

  2. 计算参数列表位置:通过栈帧指针和参数类型大小,va_start宏可以计算出参数列表中各个参数的位置。这通常涉及指针运算,根据参数类型大小来移动指针位置。

  3. 保存参数列表信息:va_start宏将参数列表位置信息保存在一个va_list类型的变量中,以便后续的函数进行处理。可以将栈帧指针和计算得到的参数列表位置信息存储在va_list变量中。

va_start宏使用一些编译器和操作系统提供的底层机制来实现可变参数的处理。具体实现可能会因编译器和操作系统的不同而异,也可能受到编译器的优化策略的影响。

<2>.v2.0

#include <stdio.h>
#include <stdarg.h>char* format_string(const char* format, ...)
{va_list args;char* str;// 初始化可变参数列表va_start(args, format);// 格式化字符串并存储到动态分配的字符串中int length = vasprintf(&str, format, args);// 结束可变参数列表va_end(args);printf("Formatted String: %s\n", str);printf("String Length: %d\n", length);return str;
}int main()
{char* result = format_string("Hello %s, your age is %d.", "John", 25);// 输出 Formatted String: Hello John, your age is 25.// 输出 String Length: 30free(result);  // 释放动态分配的字符串return 0;
}

va_end是一个宏,用于结束对可变参数列表的访问。它的原理是基于C语言的可变参数机制。

va_end宏的工作原理如下:

  1. 首先,它接收一个va_list类型的变量作为参数,该变量保存了参数列表的位置信息。

  2. 接着,通过一系列机制(如编译器和操作系统的底层支持)实现将参数列表进行清理和释放的操作。

  3. 最后,将va_list类型的变量标记为无效,以确保之后对它的访问是无效的。

具体实现的细节可能因编译器和操作系统而异,但通常会涉及以下步骤:

  1. 清理参数列表:va_end宏根据参数列表的位置信息,使用特定的机制将参数列表进行清理。它可能涉及释放资源、清理栈上的参数值等操作。具体的清理操作由编译器和操作系统提供的底层支持来实现。

  2. 使va_list变量失效:为了确保在之后对va_list变量的访问是无效的,va_end宏将该变量标记为无效。这样可以避免误用已经结束的参数列表。

va_end宏的实现依赖于编译器和操作系统的底层支持。具体实现的细节可能会因编译器和操作系统的不同而异。但无论实现细节如何,va_end宏的目标都是确保正确清理和释放可变参数列表所占用的资源,并将va_list变量标记为无效。

<3>.v3.0

#include <iostream>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <string>using namespace std;string AStringPrintf(const char *format, ...) {va_list ap;va_start(ap, format);char *buffer;int bufferSize = vasprintf(&buffer, format, ap);va_end(ap);if(bufferSize < 0) {return string();}string result(buffer);free(buffer);buffer = NULL;return result;
}int main(){char str[64]={1,2,3,5,6,7,8,9};string buf =  AStringPrintf(str);printf("buf = %s\n",buf.c_str());
}
  1. vsnprintf函数接收一个格式化字符串和一个va_list类型的参数列表。利用格式化字符串,它将参数列表中的数据转换为相应的字符串格式。

  2. 首先,vsnprintf函数根据格式化字符串中的格式指示符,逐个读取参数列表的值,并根据指示符的要求对其进行格式化。

  3. 然后,vsnprintf函数根据格式化的结果,将其写入到指定的缓冲区中。它会确保写入的数据不超过指定的缓冲区大小。

  4. 最后,vsnprintf函数会在写入完成后,返回实际写入的字符数(不包括结尾的’\0’)。如果缓冲区大小不足以容纳格式化后的字符串,vsnprintf函数会截断字符串,但仍然会返回实际要写入的字符数。

需要注意的是,由于vsnprintf函数是经过格式化而得到的字符串的长度是不确定的,因此在使用之前需要分配足够的缓冲区来存储格式化后的字符串,以避免缓冲区溢出的情况发生。

vsnprintf函数是一个用于以固定格式将可变参数格式化为字符串的函数。它将格式化的结果写入指定的缓冲区,并返回实际写入的字符数。这个函数在C++中可用于处理可变参数,并将其转换为字符串格式。

<4>.v4.0

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>void dynamic_print(const char* format, ...)
{va_list args;va_start(args, format);char* dyn_str = NULL;size_t str_length = 0;// 计算动态生成字符串所需的长度str_length = vsnprintf(NULL, 0, format, args);// 为字符串动态分配内存dyn_str = (char*)malloc(str_length + 1);// 动态生成字符串vsnprintf(dyn_str, str_length + 1, format, args);printf("%s", dyn_str);free(dyn_str);va_end(args);
}int main(){int num1 = 10;int num2 = 20;dynamic_print("Sum: %d + %d = %d\n", num1, num2, num1 + num2);return 0;
}

相关文章:

C++之va_start、vasprintf、va_end应用总结(二百二十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…...

OpenCV自学笔记十一:形态学操作(一)

目录 1、腐蚀 2、膨胀 3、通用形态学函数 4、开运算 5、闭运算 1、腐蚀 腐蚀&#xff08;Erosion&#xff09;是数字图像处理中的一种形态学操作&#xff0c;用于消除图像中边界附近的细小区域或缩小对象的大小。腐蚀操作通过卷积输入图像与结构元素&#xff08;也称为腐…...

封装全局异常处理

文章目录 1 定义错误码类2 定义业务异常类3 全局异常处理器4 使用5 前端请求效果总结 1 定义错误码类 ​ 可以定义各种错误码枚举&#xff0c;比如业务&#xff0c;系统相关的报错信息 /*** 错误代码* 错误码** author leovany* date 2023/09/23*/ public enum ErrorCode {SU…...

python的requests响应请求,结果乱码,即使设置了response.encoding也没有用的解决方法

一、问题 如图&#xff1a; 一般出现乱码&#xff0c;我们会有三种解决方式&#xff0c;如下但是图中解决了发现还是不行, response.encodingresponse.apparent_encoding通过看网页源码对response.encodingutf8指定编码格式或者直接通过response.content.decode()来获得源码 出…...

PyCharm 手动下载插件

插件模块一直加载失败&#xff0c;报错信息&#xff1a; Marketplace plugins are not loaded. Check the internet connection and refresh. 尝试了以下方法&#xff0c;均告失败&#xff1a; pip 换源Manage Plugin Repositories...HTTP 代理设置...关闭三个防火墙 最后选…...

Gnomon绑定基础(约束 IK 节点)

点约束 方向约束 父约束 目标约束 修改后 对象方向 IK控制柄 直的骨骼&#xff0c;指定IK怎么弯曲 直的骨骼&#xff0c;指定IK怎么弯曲 样条曲线 数学节点 乘除节点 混合节点 注意...

STL常用遍历,查找,算法

目录 1.遍历算法 1.1for_earch 1.2transform 2.常用查找算法 2.1find&#xff0c;返回值是迭代器 2.1.1查找内置数据类型 2.1.2查找自定义数据类型 2.2fin_if 按条件查找元素 2.2.1查找内置的数据类型 2.2.2查找内置数据类型 2.3查找相邻元素adjeacent_find 2.4查找指…...

BCC源码内容概览(1)

接前一篇文章&#xff1a;BCC源码编译和安装 本文参考官网中的Contents部分的介绍。 BCC源码根目录的文件&#xff0c;其中一些是同时包含C和Python的单个文件&#xff0c;另一些是.c和.py的成对文件&#xff0c;还有一些是目录。 跟踪&#xff08;Tracing&#xff09; exam…...

mysql限制用户登录失败次数,限制时间

mysql用户登录限制设置 mysql 需要进行用户登录次数限制,当使用密码登录超过 3 次认证链接失败之后,登录锁住一段时间,禁止登录这里使用的 mysql: 8.1.0 这种方式不用重启数据库. 配置: 首先进入到 mysql 命令行:然后需要安装两个插件: 在 mysql 命令行中执行: mysql> INS…...

从利用Arthas排查线上Fastjson问题到Java动态字节码技术(下)

上一篇从Arthas的源码引出了Java动态字节码技术&#xff0c;那么这一篇就从几种Java字节码技术出发&#xff0c;看看Arthas是如何通过动态字节码技术做到无侵入的源码增强&#xff1b; Java大部分情况下都是解释执行的&#xff0c;也就是解释.class文件&#xff0c;所以如果我们…...

Ubuntu中安装Anaconda 如何将 路径导入为全局变量

第一步&#xff1a;将你的anaconda 路径复制下来&#xff0c;在终端输入对应路径。 echo export PATH"/home/你的用户名/anaconda3/bin:$PATH" >> ~/.bashrc 第二步&#xff1a;在终端输入下面命令或者重启系统。 source ~/.bashrc 在对应的anaconda安装目…...

【QT】Qt的随身笔记(持续更新...)

目录 Qt 获取当前电脑桌面的路径Qt 获取当前程序运行路径Qt 创建新的文本文件txt&#xff0c;并写入内容如何向QPlainTextEdit 写入内容QTimerQMessageBox的使用QLatin1StringQLayoutC在c头文件中写#include类的头文件与直接写class加类名有何区别mutable关键字前向声明 QFontQ…...

【LeetCode-简单题】589. N 叉树的前序遍历

文章目录 题目方法一&#xff1a;单循环栈做法方法二&#xff1a;递归 题目 方法一&#xff1a;单循环栈做法 关键在于子节点的入栈顺序&#xff0c;决定了子节点的出栈顺序&#xff0c; 因为是前序遍历 所以压栈顺序先让右边的入栈 依次往左 这样左边的节点会在栈顶 这样下次…...

Linphone3.5.2 ARM RV1109音视频对讲开发记录

Linphone3.5.2 ARM RV1109音视频对讲开发记录 说明 这是一份事后记录&#xff0c;主要记录的几个核心关键点&#xff0c;有可能很多细节没有记上&#xff0c;主要是方便后面自己再找回来! 版本 3.5.2 一些原因选的是这样一个旧的版本&#xff01; 新的开发最好选新一些的版…...

Unity用相机实现的镜子效果

首先登场 场景中的元素 mirror是镜子&#xff0c;挂着我们的脚本&#xff0c;Quad是一个面片。Camera是用来生成RenderTexture给面片的。里面的test1是我用来调试位置的球。 镜子size是大小&#xff0c;x是-2&#xff0c;为了反转一下贴图 相机直接可以禁用掉&#xff0c;用…...

计算机网络分类

按照覆盖范围分类 &#xff08;1&#xff09;个域网&#xff1a;通常覆盖范围在1&#xff5e;10m。 &#xff08;2&#xff09;局域网&#xff1a;通常覆盖范围在10m&#xff5e;1km。 &#xff08;3&#xff09;城域网&#xff1a;覆盖范围通常在5&#xff5e;50 km 。 &…...

AI AIgents时代 - (三.) AutoGPT和AgentGPT

前两篇讲解了Agent的原理和组件&#xff0c;这节我将给大家介绍两个agent项目&#xff0c;给出它们的工作原理和区别&#xff0c;并教大家亲手尝试使用 Agents&#x1f389; &#x1f7e2; AutoGPT&#x1f916;️ 我们的老朋友&#xff0c;之前文章也专门写过。AutoGPT 是一…...

Jmeter接口自动化和Python接口自动化,如何选择?

选择Jmeter或Python进行接口自动化测试取决于您的具体需求和环境。以下是一些可以考虑的因素&#xff1a; 1. 语言熟悉度&#xff1a;如果您对Java更熟悉&#xff0c;那么Jmeter可能是更好的选择。而如果您的团队或个人对Python更熟悉&#xff0c;那么Python可能是更好的选择。…...

Sqilte3初步教程

文章目录 安装创建数据库创建和删除表插入行数据 安装 Windows下安装&#xff0c;首先到下载页面&#xff0c;下载Windows安装软件&#xff0c;一般是 sqlite-dll-win32-*.zip sqlite-tools-win32-*.zip下载之后将其内容解压到同一个文件夹下&#xff0c;我把它们都放在了D:\…...

详解Python中的json库

目录 1. json简介2. dumps/loads3. dump/load4. jsonl格式 1. json简介 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;用于在不同应用程序之间传递数据。它是一种文本格式&#xff0c;易于阅读和编写&#xff0c;同时也易于…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...