先来个简单的例子:#include

#include

void test0(int num,...)

{

va_list ap;

va_start(ap, num);

while(num--)

{

printf("%s ",va_arg(ap, char *));

}

va_end(ap);

}

void test1(int num,...)

{

va_list ap;

va_start(ap, num);

while(num--)

{

printf("%d ",va_arg(ap, int *));//为什么输出正确结果呢??

}

va_end(ap);

printf("\n");

}

void test2(int num,...)

{

va_list ap;

va_start(ap, num);

while(num--)

{

printf("%d ",va_arg(ap, int));

}

va_end(ap);

printf("\n");

}

void test3(int num,...)

{

va_list ap;

va_start(ap, num);

while(num--)

{

printf("%c ",va_arg(ap, char));

}

va_end(ap);

printf("\n");

}

int main()

{

test0(3, "hello", "world", "!\n");

test1(4, 1, 2, 3 ,4);

test2(2, 1, 2, 3 ,4);

test2(3, '1', '2', '3' ,'4');

return 0;

}

输出:

hello world !

1 2 3 4

1 2

49 50 51//为什么不能输出1 2 3??

可变参数中个数不定可是传入的是一个参数也可以是多个;可变参数中的每个参数的类型可以不同,也可以相同;可变参数的每个参数并没有实际的名称与之相对应,用起来是很灵活。可变参数是由宏实现的,但是由于硬件平台的不同,编译器的不同,宏的定义也不相同,下面是VC6.0中x86平台的定义:

typedef char * va_list;     // TC中定义为void*

#define _INTSIZEOF(n)

((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) //为了满足需要内存对齐的系统,求int型大小#define va_start(ap,v)    ( ap = (va_list)&v + _INTSIZEOF(v) )

#define va_arg(ap,t)

( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

#define va_end(ap) ( ap = (va_list)0 ) t为变量类型

C语言的函数形参是从右向左压入堆栈的,以保证栈顶是第一个参数,而且x86平台内存分配顺序是从高地址到低地址。因此似函数fun(int var1,int var2,...,int varN)内存分配大致上是这样的:(可变参数在中间)栈区:

|栈顶低地址|第一个参数var1                  |第二个参数var2                  后ap指向地址|...

|函数的最后varN

|...

|函数的返回地址|...

|栈底高地址va_start(ap,v);后ap = (va_list)&v + _INTSIZEOF(v)指向第二个参数地址调用va_arg(ap,t)  ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )取出当前ap指针所指的值,并使ap指向下一个参数

不过被定义为宏的东西用起来要小心,我现在用不着va_list,不过先了解点皮毛也好。

下面是msdn中的例子: beautiful

#include

#define ANSI/* Comment out for UNIX version*/

#ifdef ANSI/* ANSI compatible version*/

#include

int average( int first, ... );

#else/* UNIX compatible version*/

#include

int average( va_list );

#endif

void main( void )

{

/* Call with 3 integers (-1 is used as terminator). */

printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );

/* Call with 4 integers. */

printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );

/* Call with just -1 terminator. */

printf( "Average is: %d\n", average( -1 ) );

}

/* Returns the average of a variable list of integers. */

#ifdef ANSI/* ANSI compatible version*/

int average( int first, ... )

{

int count = 0, sum = 0, i = first;

va_list marker;

va_start( marker, first );/* Initialize variable arguments. */

while( i != -1 )

{

sum += i;

count++;

printf(" %d sum: %d", i, sum);

i = va_arg( marker, int);

}

va_end( marker );/* Reset variable arguments.*/

return( sum ? (sum / count) : 0 );

}

#else/* UNIX compatible version must use old-style definition.*/

int average( va_alist )

va_dcl

{

int i, count, sum;

va_list marker;

va_start( marker );/* Initialize variable arguments. */

for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )

sum += i;

va_end( marker );/* Reset variable arguments.*/

return( sum ? (sum / count) : 0 );

}

#endif

结果:

2 sum: 2 3 sum: 5 4 sum: 9Average is: 3

5 sum: 5 7 sum: 12 9 sum: 21 11 sum: 32Average is: 8

Average is: 0

Press any key to continue

在来一个简单的例子:#include #include

void print(char *format,...);    //自定义输出格式void print(char *format,...)

{

va_list argptr;

va_start(argptr, format);

while(*format != '\0')

{

switch(*(format++))

{

case 's': printf("%s ", va_arg(argptr, char *)); break;

case 'i': printf("%d ", va_arg(argptr, int)); break;

case 'c': printf("%c ", va_arg(argptr, char)); break;

case 'f': printf("%.1f\n", va_arg(argptr, double)); break;

default: break;

}

}

va_end(argptr);

}

int main()

{

print("sicft","laomou",24,'M',120.0);    //输出格式依次为string, integer, char, float

return 0;

}

next用法C语言,C语言可变参数的使用相关推荐

  1. c语言理解参数,c语言中对可变参数列表的简单理解

    函数原型中一般情况下参数的数目是固定的,但是如果想在不同的时候接收不定数目的参数时该怎么办呢?c语言提供了可变参数列表来实现. 可变参数列表是通过宏来实现的,这些宏定义在stdarg.h的头文件中.头 ...

  2. C语言中函数可变参数解析

    大多数时候,函数中形式参数的数目通常是确定的,在调用时要依次给出与形式参数对应的所有实际参数.但在某些情况下希望函数的参数个数可以根据需要确定.典型的例子有 大家熟悉的函数printf().scanf ...

  3. 编写可变参数函数 c语言,C语言中编写可变参数函数

    通过stdarg.h头文件为函数提供了定义可变参数列表的能力.声明一个可变参数的函数类似: void f1(int n,...); 其中n表示参数列表个数,而用省略号来表示未知参数列表.stdarg. ...

  4. 【转载】c语言中的可变参数编程

    在c语言中使用变长参数最常见的就是下面两个函数了: int printf(const char *format, ...);int scanf(const char *format, ...); 那他 ...

  5. 【嵌入式】C语言高级编程-可变参数宏(12)

    00. 目录 文章目录 00. 目录 01. 可变参数宏概述 02. ##符号 03. 可变参宏另外一种写法 04. 内核中的可变参数宏 05. 附录 01. 可变参数宏概述 #include < ...

  6. 【C/C++开发】C语言实现函数可变参数

    函数原型: int printf(const char *format[,argument]...)        返 回 值: 成功则返回实际输出的字符数,失败返回-1.  函数说明:        ...

  7. 【C语言进阶深度学习记录】三十九 C语言中的可变参数(参数可变的函数)

    用过printf()函数的热都知道,printf的参数可以有多个,它是可变的,根据我们输出参数的类型以及个数的不同来确定参数.今天来学习C语言中参数可变的函数是如何实现的. 文章目录 1 可变参数 2 ...

  8. C语言学习笔记---可变参数

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

  9. c语言va_start函数,va_start和va_end,以及c语言中的可变参数原理

    FROM:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html 本文主要介绍va_start和va_end的使用及原理. 在 ...

  10. C语言_函数可变参数列表

    函数可变参数列表的应用和原理 在网上看到各位前辈关于这部分的介绍有些是过于简洁,有些则是过于晦涩,有的代码拿出来甚至在编译器上跑不过去,所以在这里讲一下自己对于可变参数的认识,若有不正确的地方,欢迎各 ...

最新文章

  1. 开源吞噬世界,得开发者得天下
  2. Explore the Service Console
  3. springboot 各种日志打印
  4. Mysql的安装和配置
  5. flutter向上动画弹出菜单效果
  6. 计算机网络课设telnet_【川大】计算机网络课程设计9013,奥鹏2017
  7. 升哲科技 x 百度智能云丨智能全感知系统,挽救 127 个生命的城市安全方案
  8. Java中线程安全的单例模式
  9. 谈谈流计算中的『Exactly Once』特性
  10. linux小红帽网卡设定,LINUX红帽子怎么配置上网
  11. 整数规划:分支定界法
  12. oppo9s刷机教程_OPPOR9SPlus官方固件刷机教程_线刷|救砖教程图解
  13. 计算机u盘读不出来,详细教你解决电脑读不出u盘
  14. [论文笔记]Fader Networks: Manipulating Images by Sliding Attributes(2017 NIPS)
  15. 实时文件同步工具-端端Clouduolc在项目研发中的使用体会
  16. 关于微信第三方平台$APPID$.wx.abc.com的问题
  17. C语言指针-什么是指针,如何引用指针
  18. zxl-机器学习-01
  19. 61、智能指针类模板
  20. java用hutool.excelUtil实现excel创建模板和下载模板

热门文章

  1. SLF4J 之logback.xml配置文件实例及其说明
  2. Python核心模块——urllib模块
  3. 基于easyui开发Web版Activiti流程定制器详解(五)——Draw2d详解(一)
  4. Oracle查看SQL执行计划的方式
  5. 大白话系列之C#委托与事件讲解(一)
  6. MySQL主从复制配置过程(一主一从模式)
  7. GIT之git及git服务搭建
  8. 华为某研究生程序员哀叹:年薪五十多万,存款一百万,却不知道未来怎么走!...
  9. vivo统一告警平台建设与实践
  10. 头条一面:Spring IOC容器中只存放单例Bean吗?