c语言取出可变参数,C语言可变参数va_list

#include

#include

#include

/*

1. 使用va_list va_start va_arg va_end实现可变参数

*/

void simple_va_fun(int i, ...) {

va_list arguments;

int j = 0;

int k, m;

va_start(arguments, i);

j = va_arg(arguments, int);

m = va_arg(arguments, int);

va_end(arguments);

printf("%d,%d,%d\n",i,j,m);

}

/*

2. 固定参数函数

*/

void fixed_args_func(char x, int a, double b, char *c)

{//打印参数在栈中的地址

printf("x = 0x%p\n", &x);

printf("a = 0x%p\n", &a);

printf("b = 0x%p\n", &b);

printf("c = 0x%p\n", &c);

}

/*

3. 实现自己的可变参数,实则是按顺序从栈中取出参数的值

*/

void var_args_func(const char * fmt, ...) {

char* ap;

ap = (char *)&fmt + sizeof(fmt);

int* int_ap = (int *)ap;

printf("first:%d\n",*int_ap);

int_ap = int_ap + 1;

printf("second:%d\n",*int_ap);

int_ap = int_ap + 1;// string start index

char* c_ptr = (char*)int_ap;

char* str = (char* )*int_ap;

printf("&int_ap = 0x%p\n",int_ap);

printf("&c_ptr  = 0x%p\n", c_ptr);

printf("&str    = 0x%p\n",str);

//栈里面存储的是指向字符串"helloworld的指针",即二级字符指针

printf("third1:%s\n",str);

printf("third2:%s\n", *(char **)int_ap);

}

//stdarg.h 中提供的标准可变参数宏

void std_vararg_func(const char *fmt, ...) {

va_list ap;

va_start(ap, fmt);

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

printf("%f\n", va_arg(ap, double));

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

va_end(ap);

}

int main() {

//fixed_args_func('a',17, 5.40, "hello world");

//char* p = "xiongwei";

//printf("%d\n",sizeof(p));

var_args_func("%d %d %s\n", 4, 5, "helloworld");

printf("--------------------------------------\n");

std_vararg_func("%d %f %s\n", 4, 5.4, "helloworld");

system("pause");

return 0;

}

对比一下 std_vararg_func和var_args_func的实现,va_list似乎就是char*, va_start似乎就是((char*)&fmt) + sizeof(fmt),va_arg似乎就是得到下一个参数的首地址。没错,多数平台下stdarg.h中va_list, va_start和var_arg的实现就是类似这样的。一般stdarg.h会包含很多宏,看起来比较复杂。在有的系统中stdarg.h的实现依赖some special functions built into thethe compilation system to handle variable argument lists and stack allocations,多数其他系统的实现与下面很相似:(Visual C++ 6.0的实现较为清晰,因为windows上的应用程序只需要在windows平台间做移植即可,没有必要考虑太多的平台情况)。

output://

first:4

second : 5

& int_ap = 0x003EF968

& c_ptr = 0x003EF968

& str = 0x013780D4

third1 : helloworld

third2 : helloworld

--------------------------------------

4

5.400000

helloworld

实现Printf()函数:#include "stdio.h"

#include "stdlib.h"

void myprintf( char* fmt, ... )         /* 一个简单的类似于printf的实现,//参数必须都是int 类型 */

{

char* pArg = NULL;          /* 等价于原来的va_list */

charc;

pArg= (char *) &fmt;        /* 注意不要写成p = fmt !!因为这里要对//参数取址,而不是取值 */

pArg+= sizeof(fmt);         /* 等价于原来的va_start */

do

{

c = *fmt;

if ( c != '%' )

{

putchar( c );   /* 照原样输出字符 */

}else     {

/*按格式字符输出数据 */

switch ( *++fmt )

{

case 'd':

printf( "%d", *( (int *) pArg) );

break;

case 'x':

printf( "%#x", *( (int *) pArg) );

break;

default:

break;

}

pArg += sizeof(int);    /* 等价于原来的va_arg */

}

++fmt;

}

while ( *fmt != '\0' );

pArg = NULL;                            /* 等价于va_end */

return;

}

int main( int argc, char* argv[] )

{

inti= 1234;

intj= 5678;

myprintf( "thefirst test:i=%d", i, j );

myprintf( "thesecend test:i=%d; %x;j=%d;", i, 0xabcd, j );

system( "pause" );

return(0);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值