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

【C语言】可变参数列表

本篇博客让我们来认识一下C语言学习过程中往往被忽略的可变参数列表

所谓可变参数,就是一个不限定参数数量的函数,我们可以往里面传入任意个数的参数,以达成某些目的。

关联:C++11可变模板参数;本文首发于 慕雪的寒舍

1.函数

#include <stdarg.h>void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);

1.1 va_start

void va_start(va_list ap, last_arg);
  • ap: 这是一个 va_list 类型的对象,它用来存储通过 va_arg 获取额外参数时所必需的信息
  • 这个函数的作用是初始化 ap 变量,它与 va_argva_end 函数一起使用。
  • last_arg 是最后一个传递给函数的已知的固定参数,即省略号之前的参数

要想设置一个带可变参数的函数,函数声明是下面这样的

void test(int a,int b, ...);

这里出现的省略号就是可变参数的特征,而变量b就是va_start函数需要的last_arg

1.2 va_arg

type va_arg(va_list ap, type);

这个函数的作用是来提取可变参数列表中的参数。注意,每次提取的参数是直接返回的,并没有放到变量ap中。

每次对va_arg的调用都会修改ap,以便下次调用时,返回下一个参数;推断参数的时候需要指定type,如果当前参数类型和type不统一,就会发生不可预知的错误(man手册里面说的)

If ap is passed to a function that uses va_arg(ap,type) then the value of ap is undefined after the return of that function.

如果ap被传递给va_arg(ap,type),则在该函数返回后,ap的值未定义。

1.3 va_end

void va_end(va_list ap);

每一个va_start都需要有一个配套的va_end,其用于清空ap

可以把他俩的关系理解为malloc/free,记得加上就行

1.4 va_copy

这个函数的作用是将可变参数列表从第二个参数src拷贝到第一个参数dest

void va_copy(va_list dest,va_list src);

其也能够初始化dest。调用了va_copy后,无须调用va_start初始化dest,但va_end还是需要的。

2.简单示例

2.1 打印多个参数

#include<stdarg.h>
#include<stdio.h>
int print(int num_args,...)
{va_list ap;va_start(ap,num_args);//初始化可变参数for(int i=0;i<num_args;i++){printf("%d ",va_arg(ap,int));}printf("\n");va_end(ap);//结束对ap的使用
}int main()
{print(5,1,2,3,4,5,6,7,8,9);return 0;
}

运行该函数,会打印如下结果

$ ./test
1 2 3 4 5 

这就表明了,...省略号之前的参数,和va_arg返回可变参数其实是没有关系的。

int print(int num_args,...)
{va_list ap;va_start(ap,num_args);//初始化可变参数for(int i=0;i<8;i++){printf("%d ",va_arg(ap,int));}printf("\n");va_end(ap);//结束对ap的使用
}int main()
{print(5,1,2,3,4,5,6,7,8,9,10);return 0;
}

即便在最后都没有使用num_args,也不会影响结果的正确性。va_start需要这个参数,其实是用来标识可变参数的起点。

$ ./test
1 2 3 4 5 6 7 8 

2.2 多参数求和

#include<stdarg.h>
#include<stdio.h>
// 采用可变参数,第一个参数用于标识参数数量
int sum(int num_args, ...)
{int val = 0;va_list ap;int i;va_start(ap, num_args);for(i = 0; i < num_args; i++){val += va_arg(ap, int);}va_end(ap);return val;
}void test1()
{printf("10、20 和 30 的和 = %d\n",  sum(3, 10, 20, 30) );printf("4、20、25 和 30 的和 = %d\n",  sum(4, 4, 20, 25, 30) );
}

运行如下

$ ./test
10、20 和 30 的和 = 60
4、20、25 和 30 的和 = 79

3.利用可变参数实现log类

现在有了可变参数,我们就可以接用这个参数来进行日志的打印了

#pragma once#include <cstdio>
#include <ctime>
#include <cstdarg>
#include <cassert>
#include <cstring>
#include <cerrno>
#include <stdlib.h>#define DEBUG 0
#define NOTICE 1
#define WARINING 2
#define FATAL 3const char *log_level[]={"DEBUG", "NOTICE", "WARINING", "FATAL"};// 采用可变参数列表
void logging(int level, const char *format, ...)
{assert(level >= DEBUG || level <= FATAL);char *name = getenv("USER");// 获取环境变量中的用户(执行命令的用户)char logInfo[1024];// 获取可变参数列表va_list ap; // ap -> char*va_start(ap, format);vsnprintf(logInfo, sizeof(logInfo)-1, format, ap);va_end(ap); // ap = NULL// 根据日志等级选择打印到stderr/stdoutFILE *out = (level == FATAL) ? stderr:stdout;// 格式化打印到文件中fprintf(out, "%s | %u | %s | %s\n", \log_level[level], \(unsigned int)time(nullptr),\name == nullptr ? "unknow":name,\logInfo);
}

3.1 vsnprint

作用:使用vsnprintf()用于向一个字符串缓冲区打印格式化字符串,且可以限定打印的格式化字符串的最大长度。

此函数需要C99或者C++11及以上版本才能支持。

int vsnprintf(char* sbuf, size_t n, const char* format, va_list arg);
  • 第一个参数:目标缓冲区(字符数组)
  • 第二个参数,限定最多打印到缓冲区的字符数量为n-1个(留位置给\0
  • 第三个参数,打印的格式(如%d:%s
  • 第四个参数,可变参数arg,需要用va_start初始化

返回:成功打印到sbuf中的字符的个数,不包括末尾追加的\0。如果格式化解析失败,则返回负数。

用这个函数,就能把我们的来源字符串给输入到缓冲区char logInfo[1024];

3.2 fprintf

使用fprintf,将printf的输出打印到指定文件中;用法和printf是一样的

int fprintf(FILE *stream, const char *format, ...);

这样是为了区分stderr/stdout。同时添加上执行命令的用户信息,以及当前的时间戳

    fprintf(out, "%s | %u | %s | %s\n", \log_level[level], \(unsigned int)time(nullptr),\name == nullptr ? "unknow":name,\logInfo);

3.3 运行结果

int main()
{logging(DEBUG, "socket create success: %d", 114514);logging(FATAL, "socket:%s:%d", strerror(errno), 11234);return 0;
}
$ ./test
DEBUG | 1675322313 | muxue | socket create success: 114514
FATAL | 1675322313 | muxue | socket:Success:11234

The end

对于可变参数的简单介绍就到这里!基本的使用能看懂久OK啦!

相关文章:

【C语言】可变参数列表

本篇博客让我们来认识一下C语言学习过程中往往被忽略的可变参数列表 所谓可变参数&#xff0c;就是一个不限定参数数量的函数&#xff0c;我们可以往里面传入任意个数的参数&#xff0c;以达成某些目的。 关联&#xff1a;C11可变模板参数&#xff1b;本文首发于 慕雪的寒舍 …...

目标检测的旋框框文献学习

这是最近打算看完的文献&#xff0c;一天一篇 接下来将记录一下文献阅读笔记&#xff0c;避免过两天就忘了 RRPN 论文题目&#xff1a;Arbitrary-Oriented Scene Text Detection via Rotation Proposals 论文题目&#xff1a;通过旋转方案进行任意方向的场景文本检测&#x…...

Hive 在工作中的调优总结

总结了一下在以往工作中&#xff0c;对于Hive SQL调优的一些实际应用&#xff0c;是日常积累的一些优化技巧&#xff0c;如有出入&#xff0c;欢迎在评论区留言探讨~ EXPLAIN 查看执行计划 建表优化 分区 分区表基本操作&#xff0c;partitioned二级分区动态分区 分桶 分…...

每天一道大厂SQL题【Day09】充值日志SQL实战

每天一道大厂SQL题【Day09】充值日志SQL实战 大家好&#xff0c;我是Maynor。相信大家和我一样&#xff0c;都有一个大厂梦&#xff0c;作为一名资深大数据选手&#xff0c;深知SQL重要性&#xff0c;接下来我准备用100天时间&#xff0c;基于大数据岗面试中的经典SQL题&#…...

MATLAB 遗传算法

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…...

探讨 Java 中 valueOf 和 parseInt 的区别

前言 在编程中&#xff0c;遇到类型转换&#xff0c;好像会经常用到 parseInt 和 valueOf&#xff0c;当然这里只拿 Integer 类型进行陈述&#xff0c;其他类型也是雷同的&#xff1b; 想必有读者也跟我一样&#xff0c;经常交叉使用这两个方法&#xff0c;但却不知道这两者到…...

JSON学习笔记

♥课程链接&#xff1a;【狂神说Java】一小时掌握JSON_哔哩哔哩_bilibili配套的当然还要学习ajax不管是前端后端&#xff0c;感觉这部分内容是必须的&#xff0c;不然真的做项目的时候云里雾里。总体json的内容不多&#xff0c;具体就&#xff1a;1. 列表、对象等语法格式2. js…...

家政服务小程序实战教程07-轮播图组件

小程序中首页一般显示轮播图的功能&#xff0c;点击轮播图会跳转到具体的一篇文章或者是产品&#xff0c;本篇我们就介绍一下轮播图功能的开发 01 设计数据源 我们轮播图组件需要两个字段&#xff0c;一个是展示的图片&#xff0c;一个是跳转页面传入的参数。打开数据源&…...

MySQL之索引创建、删除、唯一索引、普通索引、及命名规则、注意事项

一、MySQL 索引 定义 索引是一个数据结构&#xff0c;用于加速数据库表中数据的查询。索引存储了一些数据表中的列值&#xff0c;以及这些列值在数据表中的位置&#xff0c;这样就可以通过索引来快速查找到数据表中的某一行数据。 MySQL 支持多种索引类型&#xff0c;包括普通…...

【C++设计模式】学习笔记(3):策略模式 Strategy

目录 简介动机(Motivation)模式定义结构(Structure)要点总结笔记结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金…...

Java——聊聊JUC中的ThreadLocal

文章目录&#xff1a; 1.什么是ThreadLocal&#xff1f; 1.1 api介绍 1.2 最简单的案例认识ThreadLocal 1.3 线程池结合ThreadLocal案例 2.Thread &ThreadLocal & ThreadLocalMap 3.ThreadLocal内存泄漏问题 3.1 四大引用之强引用 3.2 四大引用之软引用 3.3 四…...

软件工程(4)--螺旋模型

前言 这是基于我所学习的软件工程课程总结的第四篇文章。 在软件开发过程中必须及时识别和分析风险&#xff0c;并且采取适当措施以消除或减少风险的危害。构建原型是一种能使某些类型的风险降至最低的方法。为了降低交付给用户的产品不能满足用户需要的风险&#xff0c;一种行…...

图解LeetCode——剑指 Offer 50. 第一个只出现一次的字符

一、题目 在字符串 s 中找出第一个只出现一次的字符。如果没有&#xff0c;返回一个单空格。 s 只包含小写字母。 二、示例 2.1> 示例 1: 【输入】s "abaccdeff" 【输出】b 2.2> 示例 2: 【输入】s "" 【输出】 限制&#xff1a; 0 < s 的…...

《HTML 5与CSS 3核心技法》读书笔记

目录前言第1章 写在前面第2章 HTML 语法基础第3章 布局类元素 &#xff0c;房子的楼板、柱子和大梁第4章 功能类元素&#xff0c;房子的门、窗、水管和电气第5章 CSS基础第6章 选择器&#xff0c;确定样式的作用范围选择器类型选择器的组合使用第7章 权重&#xff0c;样式发送冲…...

【沐风老师】3DMAX几何投影插件Geometry Projection使用详解

【几何投影插件】 描述 3DMAX几何投影插件Geometry Projection&#xff0c;将一个或多个对象或它的顶点选择沿全局或局部 x、y 或 z 轴投影到另一个对象上。 适用版本 3dMax2013或更高版本 安装设置 插件的安装非常简单&#xff0c;解压后把插件脚本 “geometry_projectio…...

面试问题整理

20200422面试题 1、有nginx为什么还要用gateway 2、factorybean和beanfactory有什么区别 https://www.cnblogs.com/leeego-123/p/12159574.html 2、aop原理 3、ioc原理 4、注解requestbody和responsebody区别。pathvireable和requestparam注解区别&#xff0c;feign客户端的注解…...

“区块链60人”2022赋能中国区块链创新人物名单公布

2022年11月5日&#xff0c;“2022第五届全国高校人工智能大数据区块链教育教学创新论坛”在京隆重召开。此次论坛公布了“区块链60人”2022赋能中国区块链创新人物评选活动获评名单。 本次评选活动通过媒体报道、第三方推荐、专家评选等环节&#xff0c;坚持“公开、公平、公正…...

day2324 数组

文章目录相关概念codeArrayTest08 数组拷贝相关概念 day23课堂笔记 1、数组 1.1、数组的优点和缺点&#xff0c;并且要理解为什么。 第一&#xff1a;空间存储上&#xff0c;内存地址是连续的。 第二&#xff1a;每个元素占用的空间大小相同。 第三&#xff1a;知道首元素的内…...

【Python实战】神仙运气—快看看你的彩票:2千多万元大奖无人领,马上就过期了,下一期的中奖者会是你吗?(纯技术交流)

前言 越努力越幸运 哈喽~我是栗子同学&#xff01; 特别注意&#xff1a;不管是沉迷赌球&#xff0c;还是沉迷购彩&#xff0c;都是不可取的。本文纯是一个技术学习内容。 听说关注我的人会暴富哦&#xff01;、 所有文章完整的素材源码都在&#x1f447;&#x1f447; 粉丝…...

2023年上半年软考高项信息系统项目管理师2月25日开班

信息系统项目管理师是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目之一&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资…...

数据库(第一天)

文档信息 文档类别正式文档文档编号数据库基础课 1.2-001版本1.2-001文档名称数据库基础课编写负责人/编写时间梁昭东/2023 年 1 月 30 日审核负责人/审核时间年 月 日批准人/批准时间年 月 日 变更记录 日期版本号变更内容修订者2023.01.30v1.2版根据实际情况增删了部分内容…...

一文了解 ArrayList 的扩容机制

了解 ArrayList 在 Java 中常用集合类之间的关系如下图所示&#xff1a; 从图中可以看出 ArrayList 是实现了 List 接口&#xff0c;并是一个可扩容数组&#xff08;动态数组&#xff09;&#xff0c;它的内部是基于数组实现的。它的源码定义如下&#xff1a; public class A…...

牛态已成选股源码

{牛态已成} {条件选股} {其他类型} N:7; A1:(REF(H,N) HHV(H,((2 * N) 1))); B1:FILTER(A1,N); C1:BACKSET(B1,(N 1)); D1:FILTER(C1,N); A2:(REF(L,N) LLV(L,((2 * N) 1))); B2:FILTER(A2,N); C2:BACKSET(B2,(N 1)); D2:FILTER(C2,N); E1:((REF(LLV(L,(2 * N)),1) REF(…...

Python基础

Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。Python 的设计具有很强的可读性&#xff0c;相比其他语言经常使用英文关键字&#xff0c;其他语言的一些标点符号&#xff0c;它具有比其他语言更有特色语法结构。小编也整理了一套关于学习Python入门…...

浅显易懂的说清楚小游戏与H5游戏的技术区别

从“跳一跳”到“羊了个羊”微信小游戏上线4年时间&#xff0c;除了涌现出不少火爆全网的小游戏之外&#xff0c;也有类似于“动物餐厅”、“口袋奇兵”等游戏得以在此孵化繁荣&#xff0c;凭借着微信强大的社交属性小游戏成为游戏厂商在桌面端、App 端、H5 端之外争夺的另一个…...

【Python入门第七天】Python 数字

Python 数字 Python 中有三种数字类型&#xff1a; intfloatcomplex 为变量赋值时&#xff0c;将创建数值类型的变量&#xff1a; 实例 x 10 # int y 6.3 # float z 2j # complex如需验证 Python 中任何对象的类型&#xff0c;请使用 type() 函数&#xff1a; 实…...

Python自动化测试 软件测试最全教程(附笔记),看完可就业

最近看到很多粉丝在后台私信我&#xff0c;叫我做一期Python自动化测试的教程&#xff0c;其实关于这个问题&#xff0c;我也早就在着手准备了&#xff0c;我录制了一整套完整的Python自动化测试的教程&#xff0c;都上传在B站上面&#xff0c;大家有兴趣的可以去看一下&#x…...

Windows 安装Tomcat

版本:tomcat8.5jdk-8u231一.解压JDK安装包 更换JDK安装路径二.解压安装Tomcat 选择jdk安装路径更换tomcat安装路径三.设置环境变量 1.“环境变量”界面中系统变量点击”新建“&#xff0c;创建CATALINA_HOMEC:\RESSET\tomcat&#xff08;Tomcat服务器的根目录&#xff09;2.创建…...

知识图谱业务落地技术推荐之图数据库汇总

0.图数据库排名 链接:https://db-engines.com/en/ranking/graph+dbms 0.1简要分析(各种图数据库属性) Neo4j(主流) 历史悠久且...

2023新华为OD机试题 - 最小传递延迟(JavaScript) | 刷完必过

最小传递延迟 题目 通讯网络中有N个网络节点 用1 ~ N进行标识 网络通过一个有向无环图进行表示 其中图的边的值,表示节点之间的消息传递延迟 现给定相连节点之间的延时列表times[i]={u,v,w} 其中u表示源节点,v表示目的节点,w表示u和v之间的消息传递延时 请计算给定源节点到…...

功能型网站 设计/青岛网站排名公司

在看Thomas Kyte大师的《Oracle Database 9i/10g/11g编程艺术》的配置环境一节有一个login.sql脚本define _editorviset serveroutput on size 1000000set trimspool onset long 5000set linesize 100set pagesize 9999column plan_plus_exp format a80column global_name new_…...

网站建设与管理是哪个软件/关键词seo优化软件

http://youngking999999.blog.163.com/blog/#m0&t1&cfks_087068084083085065085080083095085085085067085094094074087在一位博友那里看到这些经典屁话&#xff0c;觉得有意思&#xff0c;引用来给我自己看。原因很简单&#xff0c;它一部分为经典&#xff0c;一部分是…...

b2c购物网站诈骗/免费观看行情软件网站进入

默认不支持lvm分区&#xff0c;因此安装完成后直接重启&#xff0c;grub引导不成功&#xff0c;此时只能以live-cd模式启动&#xff0c;remount然后chroot到新系统&#xff0c;重新安装lvm2的包。 安装完成后继续测试&#xff0c;先不要重启; 6 mount /dev/mapper/vg-root /mn…...

福州官网网站建设/搜狗收录入口

在HTML界面开发中&#xff0c;经常会遇见JS对TABLE表格的操作&#xff0c;下面针对几种经常性的操作进行汇总&#xff1a; 第一&#xff1a;JS动态增加表格行数据 在body中定义一个空的Table <div id"detail" class"sub-title4" align"left"…...

动态网站建设 教程/搭建一个网站的流程

Architecture: i386 32bit Machine Ubuntu 16.04Linux version: 4.15.0-39-generic目录Normal 虚拟内存区在 IA32 体系结构中&#xff0c;由于 CPU 的地址总线只有 32 位&#xff0c;在不开启 PAE 的情况下&#xff0c;CPU可以访问 4G 的线性地址空间。Linux 采用了 3:1 的策略…...

浏览器怎么打开网站服务器设置/广告营销推广方案

此题不具有代表性 也不怎么好I Hate It Time Limit: 9000/3000 MS (Java/Others)Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 14776Accepted Submission(s): 5722Problem Description很多学校流行一种比较的习惯。老师们很喜欢询问&#xff0c;从某某到某…...