C语言 可变参数列表及相关宏

本文章介绍一下C语言中一些跟可变参数相关的宏及其用法

这里写目录标题

  • 引言
  • va_list
  • va_start
  • va_arg
  • va_end
  • 以上函数的联合使用样例:
  • vsnprintf
  • __VA_ARGS_

引言

C语言中有很多的带有可变参数的函数,例如printf函数,它的定义其实是类似这样子的

void printf(char *format,...);

其中format为格式化的数据,后面三个点是占位符,用来表示可变参数列表
如果我们想自定义带有可变参数的函数的话,format(格式化数据)必须是函数中参数列表的最后一个固定参数,接下来介绍几个跟可变参数列表有关的宏

宏和函数不同,宏在预处理阶段就会被展开,其实现由编译器提供,通常会包含在相应的标准库头文件中。

va_list

#include<stdarg.h>
va_list args;

va_list数据类型代表可变参数列表,我们可以通过这个数据类型,来使用可变参数列表或者访问可变参数列表中的每一个元素,这个类型一般作为其他函数的参数来使用.

va_start

void va_start(va_list ap, last_arg);

用作初始化可变参数列表
其中 ap 是一个 va_list对象,表示可变参数列表
last_arg 是带有可变参数的函数中的最后一个固定参数

va_arg

type va_arg(va_list ap, type);

用来访问可变参数列表中的某一个参数,并将可变参数列表的指针往后面移动一位

具体的使用例子:

获取可变参数列表中第一个参数,参数类型为int

int num = va_arg(args,int);

获取可变参数列表中第一个参数,参数类型为char *

char *str = va_arg(args,char*);

va_end

void va_end(va_list ap);

结束对可变参数的访问

以上函数的联合使用样例:

void my_printf(char *format, ...) {va_list args;va_start(args, format); // 初始化可变参数列表char *ptr = format;while (*ptr != '\0') {if (*ptr == '%') {ptr++; // 移动到格式字符if (*ptr == 'd') {int num = va_arg(args, int); // 获取 int 类型参数printf("%d", num);} else if (*ptr == 's') {char *str = va_arg(args, char*); // 获取 char* 类型参数printf("%s", str);} else {printf("Invalid format specifier!"); // 不支持的格式符号}} else {putchar(*ptr); // 普通字符直接输出}ptr++;}va_end(args); // 结束可变参数列表
}

vsnprintf

这个是一个函数,而不是一个宏

int vsnprintf(char *str, size_t size, const char *format, va_list ap);

str 指定将格式化数据放入的字符串
size 缓冲区大小
format 格式化数据
ap 可变参数列表

这个函数和snprintf函数非常类似,都是把格式化的数据放入指定长度的字符串中,但是区别是snprintf函数的最后一个参数是三个点的可变参数列表(. . .),而vsnprintf函数的最后一个参数是 va_list类型的可变参数列表

具体使用方式

#include <stdio.h>
#include <stdarg.h>void formatString(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];int num = 42;formatString(buffer, sizeof(buffer), "The answer is: %d", num);printf("Buffer content: %s\n", buffer);return 0;
}

_VA_ARGS

如果我们想在C语言中定义有可变参数的宏的话,就需要使用这个宏

//最简单的定义
#define my_print1(...)  printf(__VA_ARGS__)//搭配va_list的format使用
#define my_print2(format, ...) printf(format, __VA_ARGS__)  
#define my_print3(format, ...) printf(format, ##__VA_ARGS__)

如果参数列表为空的话,就需要在 __VA_ARGS_前面加上 ##,这样就会去掉前面的逗号,防止编译错误.

#include<stdio.g>
#define my_print1(...)  printf(__VA_ARGS__)
int main()
{   int a=1,b=2;my_print1("%d%d",a,b);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/674089.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TCP相关知识点

TCP相关知识点 参考&#xff1a; 《计算机网络》 (建议收藏)TCP协议灵魂之问&#xff0c;巩固你的网路底层基础 关于 TCP 三次握手和四次挥手&#xff0c;满分回答在此 (值得看) TCP处于网络体系结构中的运输层。 运输层主要为应用进程提供端到端的逻辑通信&#xff0c;然后对…

zzzzzzzzzzzzzzzzz

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 磁盘满的本质分析 专栏&#xff1a;《Linux从小白到大神》 | 系统学习Linux开发、VIM/GCC/GDB/Make工具…

Vue中的 v-if 与 v-show 的区别

概述 在 Vue.js 中&#xff0c;我们经常需要根据某些条件来显示或隐藏某些元素。这时&#xff0c;v-if 和 v-show 这两个指令就派上了用场。虽然它们都可以用来控制元素的显示与隐藏&#xff0c;但它们的实现方式、性能影响和适用场景都有所不同。 一、区别比较 1.实现方式 …

飞天使-linux操作的一些技巧与知识点7-acme申请证书

文章目录 申请一个谷歌账号 申请一个谷歌账号 申请账号略 1.进入gcloud的shell 界面 $ gcloud config set project usfesfeef $ gcloud beta publicca external-account-keys create Created an external account key [b64MacKey: 8_QhVdsfefesfesfesf6fnw770bCyfp7vz5FeCUkOo…

Snipaste使用

今天推荐一款好用的截图、贴图软件工具&#xff0c;名字叫Snipaste&#xff0c;以下是官方介绍的截图 软件官方下载地址&#xff1a; Snipaste 下载 1、截图功能 2、标注 3、开发中的使用 有时候在开发中需要临时把一些任务规则信息&#xff0c;放在代码编辑器旁边进行参考&am…

【大厂AI课学习笔记】1.5 AI技术领域(5)图像分类

CV的重要应用场景之一&#xff0c;就是图像分类。 图像分类是根据不同的语义信息区分图像&#xff0c;图像作为输入&#xff0c;分为不同的类。主要使用的方法是深度学习和神经网络。 粗粒度的图像分类&#xff0c;是比较容易的&#xff0c;哪怕是区分猫和老虎&#xff0c;但…

<网络安全>《19 安全态势感知与管理平台》

1 概念 安全态势感知与管理平台融合大数据和机器学习技术&#xff0c;提供可落地的安全保障能力&#xff0c;集安全可视化、监测、预警和响应处置于一体。它集中收集并存储客户I环境的资产、运行状态、漏洞、安全配置、日志、流量等安全相关数据&#xff0c;内置大数据存储和多…

Go基础知识学习-习题题解

Exercise: Loops and Functions&#xff0c;学习for循环 package mainimport ("fmt" )func Sqrt(x float64) float64 {z:1.0for i:0;i<10;i{z - (z*z - x) / (2*z)fmt.Println(z)}return z }func main() {fmt.Println(Sqrt(2)) }Exercise: Slices package mainim…

linux之wsl2安装远程桌面

0. 安装后的效果 1. wsl中打开terminal并安装库 sudo apt-get purge xrdp sudo apt install -y xrdp sudo apt install -y xfce4 sudo apt install -y xfce4-goodies 2.优化显示 sudo sed -i s/max_bpp32/#max_bpp32\nmax_bpp128/g /etc/xrdp/xrdp.ini sudo sed -i s/xserverbp…

安全名词解析-水坑攻击、鱼叉攻击、钓鲸攻击

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 水坑攻击02 鱼叉攻击03 钓鲸攻击 01 水坑攻击 水坑攻击&#xff08;Watering Hole Attack&#xff09;是一种针对特定目标的网络攻击方式。顾名思义&#xff0c;是在受害者必经之路设置了一个“水坑…

百亿规模京东实时浏览记录系统的设计与实现

百亿规模京东实时浏览记录系统的设计与实现 系统介绍 浏览记录系统主要用来记录京东用户的实时浏览记录&#xff0c;并提供实时查询浏览数据的功能。在线用户访问一次商品详情页&#xff0c;浏览记录系统就会记录用户的一条浏览数据&#xff0c;并针对该浏览数据进行商品维度…

分享80个行业PPT,总有一款适合您

分享80个行业PPT&#xff0c;总有一款适合您 80个行业PPT下载链接&#xff1a;https://pan.baidu.com/s/1sc44xGll2RZ8Q2aiKDbjEA?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易。知…

阿里云ECS服务器Linux安装Mysql8

链接&#xff1a;https://pan.baidu.com/s/1s9j7OhiOMV9e9Qq9GDbysA 提取码&#xff1a;dd5a --来自百度网盘超级会员V5的分享 Mysql官网:MySQL 关于Mysql Yum Repository介绍可以看下 更加简单 关于X86和ARM 传到服务器 进入所在包 cd /usr/local/develop/mysql8 解压 …

数据结构 - 线段树

1. 预制值&#xff1a; 构建的数组为&#xff0c;nums&#xff1a;【2&#xff0c; 5&#xff0c; 1&#xff0c; 4&#xff0c; 3】区间和问题&#xff0c;假设求区间 [1&#xff0c;3] 的和 2. 建树 2.1 构建线段树数组 int[] segT new int[4*n]&#xff08;为什么数组大…

代码随想录算法训练营第五十八天 | 739. 每日温度、496. 下一个更大元素 I

739. 每日温度 题目链接&#xff1a;739. 每日温度 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0…

红队打靶练习:PHOTOGRAPHER: 1

目录 信息收集 1、arp 2、nmap 3、nikto 目录扫描 1、gobuster 2、dirsearch WEB 信息收集 enum4linux smbclient 8000端口 CMS利用 信息收集 文件上传漏洞利用 提权 信息收集 get user.txt get flag 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# a…

Codeforces Round 923 (Div. 3)

Codeforces Round 923 (Div. 3) Codeforces Round 923 (Div. 3) A. Make it White 题意&#xff1a;略 思路&#xff1a;找最小和最大的‘B’下标即可 AC code&#xff1a; void solve() {cin >>n;string s; cin>> s;int mn INF, mx 0;for (int i 0; i <…

Linux文件和目录管理

目录基础 Linux操作系统以目录的方式来组织和管理系统中的所有文件。所谓的目录&#xff0c;就是将所有文件的说明信息采用树状结构组织起来。每个目录节点之下会有文件和子目录。 所有一切都从 ‘根’ 开始&#xff0c;用 ‘/’ 代表, 并且延伸到子目录。 bin&#xff1a;B…

Flink大状态和Checkpoint调优

文章迁移&#xff0c;待整理 2. 状态和Checkpoint调优 2.1 大状态调优 我们生产大多数会使用 fsState &#xff0c;memState程序挂了状态就丢了&#xff0c;应该没人会在生产使用&#xff0c;但是涉及到一些大状态&#xff0c;fsState效率很低&#xff0c;这时候会选择 roc…

ongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(2)-Swagger框架集成

Swagger是什么&#xff1f; Swagger是一个规范且完整API文档管理框架&#xff0c;可以用于生成、描述和调用可视化的RESTful风格的 Web 服务。Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口&#xff0c;可以让人和计算机拥有无须访问源码、文档或网络流量监测就…