在C语言中有些函数传递进入的参数数量是不固定的,最常见的就是 printf() 函数,它就是利用可变参数来实现任意格式的数据打印功能。 我们自己也可以编写一个参数可变的函数,每次动态的检测传入的参数,然后执行相应的动作。

  如果要自己编写参数可变的函数时,必须按照下面的步骤进行:

  1. 提供一个使用省略号的函数原型。
  2. 在函数定义中创建一个va_list类型的变量。
  3. 用宏把该变量初始化为一个参数列表。
  4. 用宏访问参数列表。
  5. 用宏完成清理工作。

  下面使用一个简单的例子来演示。

#include <stdarg.h>
int sum(int num, ...)
{va_list list;int total;int i;va_start(list,num);for(i=0;i<num;i++)total += va_arg(list,int);va_end(list);  return total;
}

  要使用可变参数必须添加头文件 stdarg.h

  首先定义一个函数,函数中第一个参数必须是形参的个数,最后一个参数必须是可变参数,用 来表示,可变参数前面可以有多个参数,但是可变参数必须是最后一个参数。

  接下来在函数体内定义一个参数列表,它的类型为va_list ,它用来存储每次读取到的参数。

  然后使用 va_start() 把参数列表拷贝到 va_list 类型的变量中。
它有两个参数,第一个是用于存储参数的列表,第二个参数是要读取参数的数量。

  接下来使用 va_arg() 函数从参数列表中依次读取各个参数,它有两个参数,第一个参数用来存储读取从参数列表中读取到的参数,第二个参数是待读取参数的类型。这里需要读取的参数都是 int 型,所以第二个参数就是 int,如果要读取的类型是 double 型,那么第二个参数就必须是 double 型。在这里要读取多个参数,所以就使用一个循环去依次读取。

  最后当所有的参数都读取完成后,就使用 va_end() 宏完成清理工作,释放存储参数时动态分配的内存。

  下面编写一段代码来测试。

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>int sum(int num, ...)
{va_list list;int total;int i;va_start(list,num);for(i=0;i<num;i++)total += va_arg(list,int);va_end(list);  return total;
}int main(int argc, char *argv[])
{int s;s= sum(3,5,3,9);    printf("%d\r\n",s);   system("pause");return 0;
}

  在主函数中调用可变参数的函数,传递给sum()函数总共有4个参数,第一个参数为3,说明后面跟着的可变参数数量是3个。然后再sum()函数中,就会使用循环读取3次,然后使用 total 变量累加3个参数的和。当sum()函数退出时就会返回三个参数的累加和。程序运行结果如下:


  改变参数数量后继续测试。


  改变参数的个数后,程序依然可以正确执行。

C语言学习笔记---可变参数相关推荐

  1. C语言学习笔记--数组参数和指针参数

    1. 数组参数退化为指针的意义 (1)C 语言中只会以值拷贝的方式传递参数,当向函数传递数组时,将整个数组拷贝一份传入函数导致执行效率低下,C 语言以高效作是最初的设计目标,所以这种方法是不可取的. ...

  2. C语言学习笔记10-指针(动态内存分配malloc/calloc、realloc、释放free,可变数组实现;Tips:返回指针的函数使用本地变量有风险!;最后:函数指针)

    C语言:指针 1. 指针:保存地址的变量 *p (pointer) ,这种变量的值是内存的地址.   取地址符& 只用于获取变量(有地址的东西)的地址:scanf函数-取地址符   地址的大小 ...

  3. c语言学习笔记【结构体02】结构体指针变量与结构体变量的函数参数,C语言学习笔记结构体02结构体指针变量与结构体变量的函数参数.docx...

    C 语言学习笔记[结构体02]结构体指针变量与结构体变量 的函数参数 C 语言学习笔记之结构体指针变量一提指针,那可 是 C 语言的核心了,有多少学子曾拜倒在指针的脚下.单纯的说指针,其实并不难,但是 ...

  4. 【Go语言 · 学习笔记】

    文章目录 Go语言 · 学习笔记 一.Go包管理 1. 什么是Go语言中的包 2. 包的命名 3. main包 4. 导入包 5. 远程包导入 6. 命名导入 7. 包的init函数 二.Go开发工具 ...

  5. (一)Go语言学习笔记

    Go语言学习笔记 1 前言 2 写Go语言需要注意的地方 2.1 Go语言编译执行和直接run的区别 2.2 Go语言的特点 2.3 Linux下配置Go环境变量 2.4 随记 3 go_code 3 ...

  6. 易语言学习笔记(2)

    易语言学习笔记(2) 1 数据类型 1.1 基本数据类型 1.1.1 数值型 1.2 特殊数据类型 1.3 数据类型长度 1.4 各数据类型初始值 1.5 数据类型间转换命令 2 易语言的命令 2.1 ...

  7. Dart 语言学习笔记(Dart语言完全指南)

    Dart 语言学习笔记 Part 1:概览 Dart是一门纯OOP语言.所有的类都继承于Object类.null也是对象,变量仅仅存储对象的引用 Dart是强类型语言,即使Dart可以进行类型推断(使 ...

  8. 梓益C语言学习笔记之链表&动态内存&文件

    梓益C语言学习笔记之链表&动态内存&文件 一.定义: 链表是一种物理存储上非连续,通过指针链接次序,实现的一种线性存储结构. 二.特点: 链表由一系列节点(链表中每一个元素称为节点)组 ...

  9. 6.方法(go语言学习笔记)

    6.方法(go语言学习笔记) 目录 定义 匿名字段 方法集 表达式 1. 定义 方法是与对象实例绑定的特殊函数. 方法是面向对象编程的基本概念,用于维护和展示对象的自身状态.对象是内敛的,每个实例对象 ...

最新文章

  1. 力扣(LeetCode)刷题,简单+中等题(第29期)
  2. matplotlib安装成功但import失败_统信UOS安装失败,deepinv20.1国产操作系统安装成功...
  3. dataconnectiondialog mysql_MySQL的DataConnectionDialog
  4. 谈谈相控阵雷达为何如此先进
  5. 线程池每次用都创建吗_跳槽涨薪季面试题之多线程(三)
  6. 浅谈面向对象的javascript几个特性
  7. java 扫雷游戏_java的扫雷小游戏(超简单)
  8. java在未来_如何在java中创建一个完整的未来
  9. 我的Python成长之路---第三天---Python基础(9)---2016年1月16日(雾霾)
  10. 【BZOJ5495】[十二省联考2019]异或粽子(主席树,贪心)
  11. 关于不使用web服务实现文本框自动完成扩展
  12. 【Websocket编程】基于libwebsockets实现客户端数据通信
  13. 从零开始制作小车TB6612控制电机
  14. 解决POI导出Excel时无法把单元格格式设置成数值类型,而不是变为货币或者自定义(附带相关问题的解决方法)
  15. white-space 与换行和空格的控制?
  16. PCB Layout爬电距离、电气间隙如何确定-安规
  17. 【语音增强论文解读 03】TCNN: TEMPORAL CONVOLUTIONAL NEURAL NETWORK FOR REAL-TIME SPEECHENHANCEMENT IN THE TIME
  18. 计算机的物理地址怎么写,电脑物理地址怎么查
  19. Apache的性能解读
  20. `MD`语法技巧Typora

热门文章

  1. 实验二 动态规划算法 最长公共子序列问题
  2. css3鼠标悬停图片抖动效果
  3. iOS开发——自定义下拉框
  4. WordPress Plupload插件未明跨站脚本漏洞
  5. JGrid有用的收藏
  6. 【python】Python的基本数据类型以及运算符的练习题
  7. GIT创建公钥,并放置远程库
  8. 对JMETER组件的认知
  9. Java基础中的基础
  10. 方法的运用_运用正确管理方法缩减库存,助力企业发展