关于va_list, va_start, va_arg, va_end

由于在C语言中没有函数重载,解决不定数目函数参数问题变得比较麻烦,即使采用C++,如果参数个数不能确定,也很难采用函数重载。对这种情况,提出了指针参数来解决问题。

**如printf()函数,其原型为:

*int printf( const char format, ...)

它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的,例如我们可以有以下不同的调用方法: printf( "%d ",i); printf( "%s ",s); printf( "the number is %d ,string is:%s ", i, s);

如何实现其功能?

我们需要以下几个宏定义:

**(1)va_list

**定义了一个指针arg_ptr, 用于指示可选的参数.

**(2)va_start(arg_ptr, argN)

**使 参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,argN是位于第一个可选参数之前的固定参数, 或者说最后一个固定参数.如有一va函数的声明是void va_test(char a, char b, char c, ...), 则它的固定参数依次是a,b,c, 最后一个固定参数argN为c, 因此就是va_start(arg_ptr, c).

**(3)va_arg(arg_ptr, type)

**返回参数列表中指针arg_ptr所指的参数, 返回类型为type. 并使指针arg_ptr指向参数列表中下一个参数.返回的是可选参数, 不包括固定参数.

**(4)va_end(arg_ptr)

**清空参数列表, 并置参数指针arg_ptr无效.

(注:va在这里是variable-argument(可变参数)的意思. 这些宏定义在stdarg.h中,所以用到可变参数的程序应该包含这个头文件)

 #include <iostream>
 #include <string>
 #include <iostream>
 using namespace std;
 #include <stdarg.h>
 void simple_va_fun(int i, ...)
 {
     va_list arg_ptr;       /// 定义可变参数指针
     va_start(arg_ptr, i);  /// i为最后一个固定参数
     int j = va_arg(arg_ptr, int); //返回第一个可变参数,类型为int
     char c = va_arg(arg_ptr, char); ///返回第二个可变参数,类型为char
     va_end(arg_ptr);  ///清空参数指针
     printf("%d %d %c", i, j, c);
     return;
 }
 ​
 int main()
 {
     simple_va_fun(100);
     cout << endl;
     simple_va_fun(100, 200);
     cout << endl;
     simple_va_fun(100, 200, 'a');
     cout << endl;
     system("pause");
     return 0;
 }

There are four parts needed:

va_list: stores the list of arguments

va_start: initializes the list

va_arg: returns the next argument in the list

va_end: cleans up the variable argument list

Whenever a function is declared to have an indeterminate number of arguments, in place of the last argument you should place an ellipsis (which looks like '...'), so, int a_function (int x, ...); would tell the compiler the function should accept however many arguments that the programmer uses, as long as it is equal to at least one, the one being the first, x

va_list is like any other variable. For example,

 va_list  a_list; 

va_start is a macro which accepts two arguments, a va_list and the name of the variable that directly precedes the ellipsis (...). So, in the function a_function, to initialize a_list with va_start, you would write va_start ( a_list, x );

va_arg takes a va_list and a variable type, and returns the next argument in the list in the form of whatever variable type it is told. It then moves down the list to the next argument. For example, va_arg ( a_list, double ) will return the next argument, assuming it exists, in the form of a double. The next time it is called, it will return the argument following the last returned number, if one exists.

To show how each of the parts works, take an example function:

 #include <cstdarg>
 #include <iostream>
 
 using namespace std;
 
 // this function will take the number of values to average
 // followed by all of the numbers to average
 double average ( int num, ... )
 {
   va_list arguments;                     // A place to store the list of arguments
   double sum = 0;
 
   va_start ( arguments, num );           // Initializing arguments to store all values after num
   for ( int x = 0; x < num; x++ )        // Loop until all numbers are added
     sum += va_arg ( arguments, double ); // Adds the next value in argument list to sum.
   va_end ( arguments );                  // Cleans up the list
 
   return sum / num;                      // Returns the average
 }
 int main()
 {
     // this computes the average of 13.2, 22.3 and 4.5 (3 indicates the number of values to average)
   cout<< average ( 3, 12.2, 22.3, 4.5 ) <<endl;
     // here it computes the average of the 5 values 3.3, 2.2, 1.1, 5.5 and 3.3
   cout<< average ( 5, 3.3, 2.2, 1.1, 5.5, 3.3 ) <<endl;
 }
 ​

C++中va_list, va_start, va_arg, va_end的基本用法的更多相关文章

  1. va_list/va_start/va_arg/va_end深入分析【转】

    转自:http://www.cnblogs.com/justinzhang/archive/2011/09/29/2195969.html va_list/va_start/va_arg/va_end ...

  2. C++省略参数(va_list va_start va_arg va_end)的简单应用

    原文参考自:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html #include <iostream> #in ...

  3. va_list/va_start/va_arg/va_end深入分析

    http://www.cnblogs.com/justinzhang/archive/2011/09/29/2195969.html

  4. va_start,va_arg,va_end的使用

    一.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表. void fun(...); void fun(parm_list,...); #include <stdi ...

  5. va_list、va_start和va_end使用

    我们知道va_start,va_arg,va_end是在stdarg.h中被定义成宏的,由于1.硬件平台的不同 2.编译器的不同,所以定义的宏也有所不同. 在ANSI C中,这些宏的定义位于stdar ...

  6. va_start(),va_end()函数应用【转】

    转自:http://www.cnblogs.com/gogly/articles/2416833.html 原理解释: VA_LIST 是在C语言中解决变参问题的一组宏,在<stdarg.h&g ...

  7. va_start(),va_end()函数应用

    原理解释: VA_LIST 是在C语言中解决变参问题的一组宏,在<stdarg.h>头文件下. VA_LIST的用法:            (1)首先在函数里定义一具VA_LIST型的变 ...

  8. 深入C语言可变参数(va_arg,va_list,va_start,va_end,_INTSIZEOF)

    一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,…),int ...

  9. OC可变參数的函数实现va_start、va_end、va_list的使用

    一.简单介绍 我们常常在编程的时候看见类似这种代码,如图1.1 图1.1 或者是这种可变參数,如图1.2 图1.2 二.基本知识介绍 在学习怎样写这样的格式的函数前,先简介几个经常使用的宏: 下面摘自 ...

  10. va_start和va_end使用详解

    本文主要介绍va_start和va_end的使用及原理. 介绍这两个宏之前先看一下C中传递函数的参数时的用法和原理: 1.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表 ...

随机推荐

  1. STL库相关练习代码

    第一题: #include <iostream> #include <vector> #include <iterator> #include <string ...

  2. 在 Rime 上对输入法进行定制

    Rime Rime是什么?忘了!但是在用.而且很好用. 了解Rime历史,还是去官网吧! 定制 Rime有两个目录: 1. 程序目录 2. 用户目录 Rime 的程序目录 Windows 上 要看你安 ...

  3. SpringIOC以及AOP注解开发

    和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作. 本质上:所有一切的操作都是 Java ...

  4. node后台项目所需中间件梳理

    0.nodemon 全局工具,监听项目文件变动,并自动重启项目 一.node内置模块 1.fs fs.readFile()  读取指定文件中的内容fs.writeFile()  向指定的文件中写入内容 ...

  5. 前端上传获取excel文件后,如何读取excel文件的内容

    1.安装xlsx npm install xlsx --save-dev 2.引入xlsx并封装读取excel方法 import * as XLSX from "xlsx"; /* ...

  6. Vuex的核心State

    State提供唯一的公共数据源,所有共享的数据都要统一放到 Store的 State 中进行存储. import Vue from 'vue' import Vuex from 'vuex' Vue. ...

  7. 高并发解决方案之 redis原子操作(适用于秒杀场景)

    秒杀活动: 秒杀场景一般会在电商网站或(APP/小程序)举行一些活动或者节假日在12306网站上抢票时遇到.对于一些稀缺或者特价商品,一般会在约定时间点对其进行限量销售,因为这些商品的特殊性,会吸引大 ...

  8. PyQt5 & PySide2信号与槽机制1

    pyside2&pyqt5的信号与槽机制 1.信号与槽的两种写法 第一种情况: from PySide2 import QtWidgets, QtCore import sys if __na ...

  9. md文件使用说明

    md文件简单使用介绍 二级标题 三级标题 斜体文本 粗体文本 粗斜体文本 分隔线 删除号 带下划线 创建脚注格式类似这样 [1]. #include <iostream> using na ...

  10. Windows 解决teamview远程必须mstsc连接

    真实原因是你的TeamViewer一直在用远程桌面的ID进行登录,所以一旦远程桌面断开,TeamViewer就无法连接了.因此我们只需要切换为服务器的TeamViewer ID即可,服务器的TeamV ...