特殊函数--变参函数及相关宏

2023-05-16

特殊函数-变参函数

定义的函数在使用时传入的参数是不定量不定类型—变参函数

include <stdarg.h>

例子:printf("abc %d def %c g\n",num,ch);
其中"abc %d def %c g\n"为固定参数,num,ch为变参列表(...)
//需要的几个宏和函数
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);

其中:
va_list是用于存放参数列表的数据结构。
va_start函数根据初始化last来初始化参数列表,last为固定参数中的最后一个固定参数.(原因在后面的宏解析中)
va_arg函数用于从参数列表中取出一个参数,参数类型由type指定。
va_copy函数用于复制参数列表。
va_end函数执行清理参数列表的工作。
//如何定义一个变参函数
格式:
返回值类型  函数名(固定参数1,固定参数2,其他固定参数, ...)
{
	va_list ap;//先定一个存放参数列表的数据
	va_start(ap,last);//last是固定参数中最后一个参数 这里是根据最后一个参数初始化变参列表
/*中间开始根据对固定参数的处理来指定后续要拿几个变参。
每次获取参数使用va_arg(ap,type) 逐个从ap中获取变参, type是指定获取的类型 注意这里每调用一次va_arg(ap,type),都会自动指向下一个变参*/
	va_end(ap);//清空参数列表
}
//应用实例
void foo(char *fmt, ...)
{
    va_list ap;//1 定义 ap
    int d;
    char c,*s;
    
    va_start(ap,fmt);//2 初始化ap,ap指向了变参列表
  
    while(*fmt)//直到遇到字符串末尾的\0时结束循环
    {
        switch (*fmt++) 
        {
            case 's': /* string */
                s = va_arg(ap, char *);//以char*类型获取参数
                printf("string %s\n", s);
                break;
            case 'd': /* int */
                d = va_arg(ap, int);
                printf("int %d\n", d);
                break;
            case 'c': /* char */
                /* need a cast here since va_arg only takes fully promoted types */
                c = (char) va_arg(ap, int);
                printf("char %c\n", c);
            break;
        }
   }
    va_end(ap);
}

宏解析

va_list

#ifdef _M_ALPHA
typedef struct 
{
	char *a0; 
	int offset; /* 下一个参数的字节偏移量 */
} va_list;
#else
typedef char * va_list;
#endif

//可以看出va_list就是使用一个char*类型来存储变参列表的

va_start、va_arg、va_end

//该宏的作用就是获取n所占的字节空间的大小sizeof(n)
#define _INTSIZEOF(n)  ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )


//该宏的作用是为了让指针指向第一个变参的首地址,&v为获取最后一个固定参数的首地址,加上_INTSIZEOF(v)(它所占空间的字节大小),这时的指针指向最后一个固定参数的后面,即变参列表的开头,这就是为什么需要用最后一个固定参数来初始化ap。
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) 


//先将ap+t类型所占空间的大小,这是的ap指向下一个参数,在减去t类型所占空间的大小然后输出。
//这样就可以做到宏va_arg最后的值为当前变参的地址,而ap指向下一个变参的地址
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) 

//将ap置为0,起到删除列表的效果
#define va_end(ap)  ( ap = (va_list)0 )

实例

使用变参函数实现若干整数相加问题

#include <stdio.h>
#include <stdarg.h>

int add(const int count,...)
{
    va_list ap;
    int n = count;
    int i;
    int sum = 0;

    va_start(ap,count);
    while(n--)
    {
        i = va_arg(ap,int);
        sum += i;
    }
    va_end(ap);
    return sum;
}

int main()
{
    int sum = add(10,1,2,3,4,5,6,7,8,9,0);
    printf("%d",sum);
    return 0;
}

输出结果:45

了解了这部分内容,那么查看printf的源码就只剩下逻辑上的问题了。

>>printf源码解读

>>数据在内存中的存储

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

特殊函数--变参函数及相关宏 的相关文章

  • 5分钟带你了解音视频开发

    前言 想赚钱 xff0c 第一点就得选对自己的方向 xff0c 有的行业和领域 xff0c 无论你如何努力 xff0c 天花板也不过如此 选对时代的风口 xff0c 就算是头猪都能被吹上天 xff0c 今天我们就来聊聊音视频开发 蓬勃发展的
  • C# 学习笔记(一)-- C# 语言和 .NET 框架

    从今天开始 xff0c 在这里记录重新学习 C 的学习笔记 导语 之前曾经自学过一段时间的 C xff0c 也写过一些 WinForm 的小工具 个人认为 C 是我所见过的用法最为优雅 xff0c 使用起来最为舒服的语言 xff0c 因此便
  • Ubuntu 添加开机/关机执行脚本与service的理解

    最近碰到一个需求是需要在ubuntu中插入一个关机脚本 xff0c 在系统关机之前执行它 在网上浏览了很多资料 xff0c 但是没有切实可行的方法 xff0c 大多数的博客都是比较陈旧的方法 xff0c 可能已经不适用于最新的ubuntu1
  • Linux 进程间通信基础(四)--fifo管道

    最近正好有一些空余时间 xff0c 在这里总结一下曾经使用过的Linux进程间通信的几种方法 xff0c 贴出来帮助有需要的人 xff0c 也有助于自己总结经验加深理解 上一次我们梳理了pipe管道的相关知识 xff0c 这一次梳理fifo
  • 利用二进制文件制作自己的Debian软件安装包

    在使用Ubuntu系统的时候 xff0c 我们已经习惯了使用Debian风格的软件安装方式 即使用apt get install命令安转或dpkg i deb的方式安装debena软件包 但有时程序没有放到Ubuntu的源服务器上且不提供d
  • Tortoise Git 克隆出现"fatal: Authentication failed for"

    使用Tortoise Git克隆时出现 34 fatal Authentication failed for 34 的错误 xff0c 并且他还不让你输入用户名和密码 xff0c 寻找了许多办法 xff0c 看到最多的是在Git Bash中
  • 怎么解决 接口请求 504 Gateway Time-out

    HTTP 504 Gateway Timeout 错误通常是由于网关或代理服务器无法在规定的时间内从上游服务器接收到响应而导致的 这可能是由于上游服务器过载或网络问题导致的 要解决此问题 xff0c 可以尝试以下步骤 xff1a 检查上游服
  • WSL无法使用npm

    报错信息 root 64 DESKTOP U2RC2DU npm bash mnt c Program Files nodejs npm bin sh M bad interpreter No such file or directory
  • HDU 3700 Line belt

    Line belt Time Limit 2000 1000 MS Java Others Memory Limit 32768 32768 K Java Others Total Submission s 3669 Accepted Su
  • Ubuntu中使用framebuffer的方法

    打开 etc initramfs tools modules文件 xff0c 在末尾加上 xff1a fbcon vesafb 打开 etc modprobe d blacklist framebuffer xff0c 找到 blackli
  • html5.超链接标签,图片标签

    lt a gt 超链接标签 a标签常用的属性 xff1a href 用于指定链接的资源 target 设置打开新资源的目标 Blank 在独立的窗口上打开新资源 self 在当前窗口打开新资源 file file协议 xff08 文件协议
  • ubuntu22.04 搭建 Pytorch环境

    关于电脑 第一步 安装anaconda 1 进入官网 链接 anaconda 2 下载linux的sh版 3 在对应位置输入 span class token function sh span 文件名 sh 4 选择 yes 5 选择no
  • opencv的ORB特征(slambook2 orb_cv.cpp代码详解)

    ORB特征提取与匹配 slambook2 ch7 orb cv cpp 1 头文件 span class token macro property span class token directive hash span span clas
  • Debian安装nodejs

    安装指定版本nodejs xff0c 以18 X版本为例 1 通过curl命令向系统中添加NodeSource存储库 curl sL https deb nodesource com setup 18 x bash xff08 如果提示 c
  • pip安装第三方库全攻略:普通安装、安装whl后缀文件、使用国内镜像安装

    简介 xff1a pip 是 Python 的包安装程序 其实 xff0c pip 就是 Python 标准库 xff08 The Python Standard Library xff09 中的一个包 xff0c 只是这个包比较特殊 xf
  • Python:处理cv2模块putText中文无法识别问题

    简介 xff1a 在cv2中 xff0c 目前putText函数中文是无法直接使用的 xff0c 需要进行一点的转换 解决办法为通过PIL模块重新封装一个函数 xff0c 直接调用 如图 xff1a 通过PIL模块改造 xff1a new
  • VLC播放电视直播rtmp流地址

    简介 xff1a RTMP是Real Time Messaging Protocol xff08 实时消息传输协议 xff09 的首字母缩写 该协议基于TCP xff0c 是一个协议族 xff0c 包括RTMP基本协议及RTMPT RTMP
  • Python:global的使用

    简介 xff1a 1 global是Python中的全局变量关键字 2 全局变量是编程术语中的一种 xff0c 源自于变量之分 3 变量分为局部与全局 xff0c 局部变量又可称之为内部变量 4 由某对象或某个函数所创建的变量通常都是局部变
  • Python:opencv画点、圆、线、多边形、矩形

    简介 xff1a 机器学习视觉方向一般都需要在图像中添加标注框 xff0c 标注框有着很大的用处 xff0c 特别是对图像中某些需要关注的特征起到圈定的效果 xff0c 方便对特征选择进行处理 相关攻略 xff1a 机器学习 xff1a 基
  • adb重启或关机手机命令

    简介 xff1a 在某些特殊场景中 xff0c 例如手机真机不在身边 xff0c 但已通过adb进行连接 xff0c 可以使用命令进行远程关机或者重启 相关攻略 xff1a adb xff1a 常用命令 adb xff1a win10系统下

随机推荐

  • docker:更换镜像源

    简介 xff1a 因为国内的网络访问问题 xff0c 为加快拉取镜像速度 xff0c 建议设置docker国内镜像源 相关攻略 xff1a win10 xff1a 安装docker和测试安装redis centos7 6 xff1a 安装d
  • 七大顶级Linux桌面比较

    1七大顶级Linux桌面 xff1a Unity 对于开源Linux平台来说 xff0c 如何选择就是首要解决的问题 通常Linux发行版都有默认的桌面成为你的首选 xff0c 但目前可供选择的桌面环境种类繁多 特别是Ubuntu系统一个平
  • Linux:安装go环境

    简介 xff1a Go xff08 又称 Golang xff09 是 Google 的 Robert Griesemer xff0c Rob Pike 及 Ken Thompson 开发的一种静态强类型 编译型语言 Go 语言语法与 C
  • docker应用:搭建私有云盘

    简介 xff1a NextCloud是一个开源的云存储解决方案 xff0c 可以在自己的服务器上搭建个人云存储系统 它提供了与市面上主流云存储服务 xff08 如Dropbox Google Drive xff09 相似的功能 xff0c
  • Flask+A-Frame:交互式全景图展示网站

    简介 xff1a 通过结合 Flask 轻量级 Web 框架与 A Frame 3D 和 VR 技术 xff0c 实现了一个可交互的全景图展示功能 xff0c 用户可以在浏览器中自由观看 旋转和缩放全景图片 项目的核心是使用 Flask 搭
  • OpenCV合成全景图

    简介 xff1a OpenCV 利用特征提取 特征匹配 齐次估计 图像配准和图像融合等技术 xff0c 将一系列图像合成为全景图 OpenCV 和 Pillow 是两个功能强大的 Python 图像处理库 xff0c 但它们在处理全景图拼接
  • BDD行为驱动开发+Python案例解析

    简介 xff1a BDD xff08 Behavior Driven Development xff0c 行为驱动开发 xff09 是一种敏捷软件开发方法 xff0c 它强调软件应该按照预期的行为来开发 BDD的核心理念是使用自然语言编写的
  • 操作系统迭代、Debian安装教程

    前言 最近在考虑公司生产环境操作系统的迭代问题 目前 xff0c 公司业务主要跑在CentOS7和8上面 xff0c 由于CentOS早已停止了7和8的支持 xff0c 新版的CentOS Stream也从RHEL的下游变成了上游 xff0
  • Debian修改DNS

    原文链接 Debian的DNS文件默认为 etc resolv conf 查看当前的DNS cat etc resolv conf 下图中画出的就是当前系统的DNS 如果想修改DNS的话 xff0c 可以直接vim 来修改文件 xff0c
  • 配置JupyterLab远程密码访问

    文章目录 部署环境配置步骤启动和连接访问启动连接访问 有些时候因为某些原因 xff08 如本地机器资源不足 数据不能离网等 xff09 xff0c 需要使用本地电脑连接远程服务器进行开发工作 xff0c 在这里记录下如何在远程Linux上配
  • linux查看 jre 安装目录

    近期对接平安银行项目 xff0c 要求放国密 jar包到jre目录 xff0c 网上也找了一些命令 xff0c 下面这个亲测有用 xff0c 特此记录一下 xff0c 我的系统版本是3 10 0 693 el7 x86 64 步骤 1 使用
  • Python选择网卡发包及接收数据包

    当一台计算机上有多个网卡时 xff0c 需要选择对应IP地址的网卡进行发送数据包或者接受数据包 1 选择网卡发包 xff08 应用scapy xff09 xff1a plface 61 conf route route 34 34 0 为对
  • php 使用 Excel/reader.php, 导入excel到数据库 ,解决The file is not readable。。

    今天小伙伴上传excel到服务器 并导入到数据库中 xff0c 可是文件一直出现 The file is not readable 是哪里的代码抛出的异常呢 xff1f 是Spreadsheet Excel Reader类里面 其中抛出异常
  • “The Language Support for Java server crashed“ 问题解决方案

    The Language Support for Java server crashed 问题解决方案 环境 xff1a Windowsvs code 1 356 14日最新发布的VSCodeJavaInstaller online win
  • (循环读取网易云缓存文件转mp3)

    循环读取网易云缓存文件转mp3 import java io DataInputStream import java io DataOutputStream import java io File import java io FileIn
  • 洛谷P4180 [BJWC2010]严格次小生成树

    传送门 之前写过一次 xff0c 但是理解不深刻 xff0c 复习之后有了更加细节的一些理解 好了进入正题 首先 xff0c 我们需要知道次小生成树一定是在最小生成树的邻集中 xff0c 即次小生成树与最小生成树只会有一条边的差别 所以我们
  • MarkDown学习笔记

    MarkDown学习笔记 目录 MarkDown学习笔记 1 标题2 段落3 文字3 1斜体3 2加粗3 3斜体 43 加粗3 4删除线3 5下划线3 6字体背景 4 分隔线5 扩展语法的说明6 高亮 xff08 需要勾选扩展语法 xff0
  • 格式化标准输出函数printf()与格式化标准输入函数scanf()

    printf 函数与scanf 函数 文章目录 printf 函数与scanf 函数格式化标准输出函数 printf 相关函数 xff1a 返回值参数执行顺序打印较长字符串格式控制符 xff1a 输出缓冲区printf 的标志转义字符类型修
  • 数据在内存中的存储

    数据在内存中的存储 文章目录 数据在内存中的存储计算机中的数据数据类型类型的基本归类整型在内存中的存储原码 反码 补码大小端介绍浮点型在内存中的存储二进制与十进制的转换 计算机要处理的信息是多种多样的 xff0c 如数字 文字 符号 图形
  • 特殊函数--变参函数及相关宏

    特殊函数 变参函数 定义的函数在使用时传入的参数是不定量不定类型 变参函数 include lt stdarg h gt 例子 xff1a printf 34 abc d def c g n 34 num ch xff09 其中 34 ab