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

2023-09-21 15:33:19

简介: 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: 6
    
    return 0;
}

<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: 30
    
    free(result);  // 释放动态分配的字符串
    
    return 0;
}

<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());
}

<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;
}

更多推荐

“深入理解SpringMVC的JSON数据返回和异常处理机制“

目录引言1.SpringMVC之JSON数据返回1.1导入依赖1.2配置弹簧-MVC.xml1.3@ResponseBody注解使用1.4.Jackson2.异常处理机制2.1为什么要全局异常处理2.2异常处理思路2.3SpringMVC异常分类2.4综合案例总结引言在现代Web开发中,SpringMVC是一个广泛使用

【SpringMVC】自定义注解

🎉🎉欢迎来到我的CSDN主页!🎉🎉🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚🌟在这里,我要推荐给大家我的专栏《SpringMVC》。🎯🎯🚀无论你是编程小白,还是有一定基础的程序员,这个专栏都能满足你的需求。我会用最简单易懂的语言,带你走进SpringMVC的世界,让你从零开始,一步步

设计模式:组合模式

目录组件代码实现优缺点源码中应用总结组合模式是一种结构型设计模式,用于将对象组织成树形结构,以表示“部分-整体”的层次结构。组合模式使得客户端可以统一地处理单个对象和组合对象,而不需要区分它们之间的差异。在组合模式中,有两种主要类型的对象:叶节点和组合节点。叶节点表示树结构中的最小单位,它们没有子节点。而组合节点则可以

求生之路2服务器搭建插件安装及详细的游戏参数配置教程linux

求生之路2服务器搭建插件安装及详细的游戏参数配置教程linux大家好我是艾西,在上一篇文章中我用windows系统给搭建演示了一遍怎么搭建自己的L4D2游戏。那么也有不少小伙伴想知道linux系统的搭建方式以及在这个过程中有什么区别。那么艾西今天就跟大家分享下用linux服务器系统搭建求生之路2(注:因PT原因本文中w

我用AI画了几张通信工程师工作照,大家看看像不像?

之前我给大家演示过AI写作。今年,我们玩点新花样,尝试一下AI绘画。我注册了百度的文心一格,打算绘制几幅和通信工程师有关的画,邀请大家一起鉴别一下AI的绘画能力。先来个简单的吧。绘画要求①:一个通信工程师在机房加班。大约十几秒钟,结果出来了——这幅画中规中矩。桌面上摆的终端不知道是啥。手是捏鼠标的姿势,可是鼠标明明就在

新概念英语(第二册)复习——Lesson 11 - Lesson15

前言一套教材,少就是多,别怀疑,别较真,努力去做,怕就怕今天用这个,明天用那个,你学十年不如别人学一年。一共96课,你可以每天1文章目录前言Lesson11-Onegoodturndeservesanother原文译文单词Lesson12-Goodbyeandgoodluck原文译文单词Lesson13-TheGree

Jmeter配置不同业务请求比例,应对综合场景压测

背景在进行综合场景压测时,遇到了如何实现不同的请求所占比例不同的问题。有人说将这些请求分别放到单独的线程组下,然后将线程组的线程数按照比例进行配置。这种方法不是很好,因为服务器对不同的请求处理能力不同,有的处理快,有的处理慢。若采取上述方案的话,并不会按照我们预期的比例进行并发。那么如何真实模拟按比例进行并发呢?此前使

【文生图系列】Stable Diffusion Webui安装部署过程中bug汇总(Linux系统)

文章目录bugs虚拟环境pythonPreparingmetadata(setup.py)gfpgan和cythonbugs看网上部署stablediffusionwebui的教程,很简单。而且我也有部署stablediffusionv1/v2的经验,想着应该会很快部署完stablediffusionwebui,但是没

【JavaEE】多线程案例-线程池

文章目录1.什么是线程池2.为什么要使用线程池(线程池有什么优点)3.如何使用Java标准库提供的线程池3.1创建一个线程池对象3.2什么是工厂模式3.3为什么要使用工厂模式3.4Executors创建不同具有不同特性的线程池3.5ThreadPool类的构造方法3.6线程池的拒绝策略3.7调用submit方法添加任务

如何使用高压放大器驱动高容性负载

使用高压放大器驱动高容性负载是一个具有挑战性的任务,需要仔细考虑电路设计和操作技巧。下面西安安泰Aigtek将为您介绍一些关于如何使用高压放大器驱动高容性负载的方法和注意事项。首先,让我们了解一下高容性负载。高容性负载通常指电容值较大的负载元件或电路,在实际应用中常见于声音系统、电力传输和电化学领域等。驱动高容性负载需

Android T 禁止应用添加窗口的操作

序什么情况下会出现我们需要禁止应用添加窗口的情况呢?假如有一个应用的窗口,我们点开后是透明的或者会影响到系统的使用,那么我们就有必要对这个窗口操作一下回顾我们在AndroidTWMS窗口相关流程中所讲的内容禁止应用添加窗口的操作有两种1.直接在客户端对应用禁止添加窗口2.在服务端禁止应用添加窗口客户端对应用禁止添加窗口

热文推荐