C语言之va_list

2023-11-06

va_list

va_list 是在C语言中解决变参问题的一组宏,变参问题是指参数的个数不定可以是传入一个参数也可以是多个;可变参数中的每个参数的类型可以不同,也可以相同;可变参数的每个参数并没有实际的名称与之相对应,用起来是很灵活。

va_list的用法

  1. 首先在函数里定义va_list 型的变量 ,这个变量是指向参数的指针 ,通过指针运算来调整访问的对象
  2. 然后用 va_start初始化变量刚定义的 va_list 变量 ,实际上 就是用 va_list 去指向函数的最后一个具名的参数;
  3. 然后用 va_arg 宏返回可变的参数,va_arg第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用 va_arg 获取各个参数);
  4. 因为栈地址是从高到低延伸的,所以加上你要的参数类型大小,就意味着栈顶指针指向你所要的参数,便可通过 底层 pop 得到。
  5. 最后用 av_end 宏结束可变参数的获取,即清空 va_list 。
  6. int vsnprintf(char *str, size_t size, const char *format, va_list ap);参数:str保存输出字符数组存储区。size存储区的大小。format包含格式字符串的C字符串,其格式字符串与printf中的格式相同arg变量参数列表,用va_list 定义。
     

#include<stdarg.h>
#include <stdlib.h>

void sum(char* msg, ...)
{
    va_list vaList;                        //定义一个va_list型的变量

    va_start(vaList, msg);                 //va_start初始化vaList
    int first = va_arg(vaList, int);       //va_arg获取第一个参数
    char* second = va_arg(vaList, char*);  //va_arg获取第二个参数
    int third = va_arg(vaList, int);       //va_arg获取第三个参数
    va_end(vaList);                        //va_end结束vaList,将vaList置NULL

    char str[256]{0};
    va_start(vaList, msg);
    vsprintf(str, msg, vaList); //配合格式化字符串,输出可变参数
    va_end(vaList);
    printf("%s", str);

    return;
}
 
 int main()
 {
     sum("hello world %d %s %d", 9, "666", 3);
     system("pause");
     return 0;
 }

snprintf

snprintf 是一个 C 标准库函数,用于格式化字符串,并将结果存储到一个字符数组中,同时限制字符串的长度

int snprintf(char *str, size_t size, const char *format, ...);
  • str:这是一个指向字符数组的指针,用于存储格式化后的字符串。
  • size:这是目标字符数组的最大容量,也就是可以写入的最大字符数(包括 null 终止符)。
  • format:这是一个格式化字符串,用于指定输出的格式,类似于 printf 中的格式化字符串。
  • ...:这是可选的参数,用于填充格式化字符串中的占位符。

例子:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char buffer[20];
    int num = 42;

    int result = snprintf(buffer, sizeof(buffer), "The answer is %d", num);

    if (result >= 0 && result < sizeof(buffer)) {
        printf("Formatted string: %s\n", buffer);
    } else {
        printf("Buffer was not large enough.\n");
    }

    return 0;
}

vsnprintf

vsnprintf,用于格式化字符串并将结果存储到字符数组中,与 snprintf 类似,但它允许你使用变长参数列表(va_list)来传递参数。这使得你可以更灵活地生成格式化后的字符串。

int vsnprintf(char *str, size_t size, const char *format, va_list ap);
  • str:这是一个指向字符数组的指针,用于存储格式化后的字符串。
  • size:这是目标字符数组的最大容量,也就是可以写入的最大字符数(包括 null 终止符)。
  • format:这是一个格式化字符串,用于指定输出的格式,与 printfsnprintf 中的格式化字符串相同。
  • ap:这是一个 va_list 类型的参数,其中包含了格式化字符串中使用的可变参数。
#include <stdio.h>
#include <stdarg.h>

void customPrintf(char *buffer, size_t size, const char *format, ...) {
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, size, format, args);
    va_end(args);
}

int main() {
    char buffer[20];

    customPrintf(buffer, sizeof(buffer), "The answer is %d", 42);

    printf("Formatted string: %s\n", buffer);

    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言之va_list 的相关文章

  • 编译时运算符

    有人可以列出 C 中可用的所有编译时运算符吗 C 中有两个运算符 无论操作数如何 它们的结果始终可以在编译时确定 它们是sizeof 1 and 2 当然 其他运算符的许多特殊用途可以在编译时解决 例如标准中列出的那些整数常量表达式 1 与
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 按成员序列化

    我已经实现了template
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 重载<<的返回值

    include
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • 接口测试工具——Postman使用详解

    目录 Postman简介 Postman主界面 菜单栏 工具栏 请求管理区 环境管理区 请求设计区 发送请求 发送GET请求 Postman发送GET请求 发送表单格式POST请求 发送JSON格式POST请求 发送XML格式POST请求
  • “invalid method declaration; return type required“

    kinda 在书面英语中使用 表示非正式发音时的 kind of 主要用作为副词 作副词时译为 有点 有几分 常用搭配 kinda like https blog csdn net qiansg123 article details 801
  • Visual studio 2019 之 如何创建一个C++项目?

    1 打开软件 进入下面的界面 点击创建新项目 2 选择空项目 点击下一步 备注 这里的选项和安装软件时 你所安装的组件有关 3 配置新项目 编辑一个自己的项目名字 选择一个保存的文件夹 然后点击右下角的创建 4 这就是项目创建后的界面 左侧
  • Python 第三方模块 数据分析 Pandas模块 时间对象与时间序列

    一 日期和时间数据类型 1 相关模块 参见 Python 内置模块 时间 部分 2 时间戳的Null值 Pandas中用pd NaT Not a Time 表示时间戳数据的Null值 gt gt gt pd NaT NaT gt gt gt
  • 安装MinGW-64 (学习笔记)

    安装MinGW 64 MinGW w64是windows版的GCC编译器 c c 编译调试 下载官网地址 往下拉页面看到下图所示 两种安装方式 方式一 在线安装 Version GCC版本 如果没有特殊的需求 一般选择最高的版本号即可 Ar
  • taro开发微信小程序禁止下拉刷新(ios下拉出现空白问题)

    一 问题描述 最近用tarojs在做一个小程序项目时 首页需要禁止下拉刷新 于是在page json里面添加了这段话 enablePullDownRefresh false 全局关闭下拉刷新 这段话确实禁止了下拉刷新 无论是安卓手机端还是苹
  • 学习Python之路之Python中常见的数据结构一——列表

    列表 List 是Python语言中最通用的序列数据结构之一 列表是一个没有固定长度的 用来表示任意类型对象的位置相关的有序集合 列表的数据项不需要具有相同的类型 常用的列表操作主要包括 索引 连接 乘法和切片等 列表中的每个元素都分配一个
  • 线性dp-----最长公共上升子序列

    首先介绍一下什么是最长公共上升子序列 对于两个数列A B 如果他们都包含一段位置不一定连续的且数值是严格递增的 那么称这一段数就是两个数列的公共上升子序列 所有公共子序列中最长的就是最长公共子序列 例 A 1 7 3 2 4 B 7 2 1
  • 阿里云dataworks离线同步

    业务场景 用公网ip 从本地mysql数据库到另一个本地mysql数据库 在dataworks上配置离线同步和调度任务 步骤 阿里云登录 1 进入dataworks 2 进入控制台 3 选择数据开发 4 配置数据源 选择mysql数据源 连
  • cmd指令杀掉某个端口或线程

    第一步 点击起始菜单 或是通过win R快捷键 在输入框中输入cmd 点击确定 即可打开dos命令窗 第二步 输入netstat ano 查询所有端口 第三步 找到你想杀掉的端口对应的 PID 比如 上面的127 0 0 1 4369对应的
  • 为什么零基础选择语言首选python

    在众多编程语言中 似乎已经没有什么能够阻挡Python的步伐 本月Python又是第一名 市场份额达到了13 42 在2023年 Python已经连续7个月蝉联榜首 遥遥领先于其他对手 每个月榜单发布后 都有小伙伴会好奇 为什么又是Pyth
  • JWT实现登陆认证及Token自动续期

    技术选型 要实现认证功能 很容易就会想到JWT或者session 但是两者有啥区别 各自的优缺点 应该Pick谁 夺命三连 区别 基于session和基于JWT的方式的主要区别就是用户的状态保存的位置 session是保存在服务端的 而JW
  • 在央企当程序员是一种怎样的体验?

    来源 zhihu com question 276681361 answer 2134441878 大家好 又到了求职季 给大家分享一段一位朋友的央企工作经历 希望对于观望工作机会的小伙伴 有些参考 我校招加入了某垄断央企 在里面从事研发工
  • 解决VS2015生成Qt5的QMainWindows界面解决方案时产生一个“表达式必须包含指针类型”的问题

    解决VS2015生成Qt5的QMainWindows界面解决方案时产生一个 表达式必须包含指针类型 的问题 问题描述 分析过程 总结 问题描述 VS2015生成了一个QMainWindow界面 我在cpp实现文件使用ui这个表达式时出现下面
  • 单链表的合并【去重】

    2个有序单链表的合并 void Mergelist L LinkList LA LinkList LB LinkList LC pa LA gt next pb LB gt next LC LA LinkList pc LC while p
  • 智能仓储管理系统(自动化仓库管理解决方案)

    企业实际的仓储管理中 往往会出现那样这样的错误 归根结底 主要是由于没使用合适的仓库管理工具 相反 人工使用合适的仓库管理工具 不仅可以在日常仓库管理方法中根据采集到的产品信息数据 大大地提高管理效率 降低库存实际管控成本 还可降低人工管理
  • 【严重】Smartbi未授权设置Token回调地址获取管理员权限

    漏洞描述 Smartbi是一款商业智能应用 提供了数据集成 分析 可视化等功能 帮助用户理解和使用他们的数据进行决策 在 Smartbi 受影响版本中存在Token回调地址漏洞 未授权的攻击者可以通过向目标系统发送POST请求 smartb
  • 个人用记录:docker启动容器之后不久就会自动关闭

    原因是 docker容器运行必须有一个前台进程 如果没有前台进程执行 容器认为空闲 就会自行退出 尝试方案1 docker run dit name jenkins p 8080 8080 jenkinsci blueocean bin b
  • JS基础-Navigator-尚硅谷-P124

    视频链接 视频 代码
  • C语言之va_list

    va list va list 是在C语言中解决变参问题的一组宏 变参问题是指参数的个数不定 可以是传入一个参数也可以是多个 可变参数中的每个参数的类型可以不同 也可以相同 可变参数的每个参数并没有实际的名称与之相对应 用起来是很灵活 va