c语言可变参数源码剖析,c语言中可变参数的原理---printf()函数

函数原型: int printf(const char *format[,argument]...)

返 回 值: 成功则返回实际输出的字符数,失败返回-1.

函数说明:

在printf()函数中,format后面的参数个数不确定,且类型也不确定,这些参数都存放在栈内.调用printf()函数时,根据format里的格式("%d %f...")依次将栈里参数取出.而取出动作要用到va_arg、va_end、va_start这三个宏定义,再加上va_list.

(1)va_list事实上是一char *类型,即:

typedef char* va_list;

(2)三个宏定义:

#define _INTSIZEOF(n)    ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define va_start(ap,v)     ( ap = (va_list)&v + _INTSIZEOF(v) )

#define va_arg(ap,type)  ( *(type *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

#define va_end(ap)          ( ap = (va_list)0 )

【attention】c语言中可变参数的原理---printf()函数

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

使用过C语言的人所再熟悉不过的printf函数原型,它的参数中就有固定参数format和可变参数(用”…”表示).而程序员又可以用各种方式来调用printf,如:

printf("%d ",value);

printf("%s ",str);

printf("the number is %d,string is:%s ",value,str);

可以看出,该函数的参数格式不固定,参数类型不固定.在C语言中使用宏来处理这些可变参数.这些宏看起来很复杂,其实原理挺简单,即根据参数入栈的特点从最靠近第一个可变参数的固定参数开始,依次获取每个可变参数的地址.

(1)宏va_start

通过该宏定义可以获取到可变参数表的首地址,并将该地址赋给指针ap.

(2)宏va_arg

通过该宏定义可以获取当前ap所指向的可变参数,并将指针ap指向下一个可变参数.注意,该宏的第二个参数为类型.

(3)宏va_end

通过该宏定义可以结束可变参数的获取.

程序员通过这三个宏定义就可以实现对可变参数的处理.例如:

#include 

typedef char* va_list;

#define _INTSIZEOF(n)    ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define va_start(ap,v)   ( ap = (va_list)&v + _INTSIZEOF(v) )

#define va_arg(ap,type)  ( *(type *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

#define va_end(ap)       ( ap = (va_list)0 )

int cal_val(int c, ...)

{

int sum = c;

va_list ap;              //声明指向char型的指针

va_start(ap,c);          //获取可变参数列表的首地址,并赋给指针ap

c = va_arg(ap,int);      //从可变参数列表中获取到第一个参数(返回值即为参数)

while(0 != c)

{

sum += c;

c = va_arg(ap,int);  //循环的从可变参数列表中获取到参数(返回值即为参数)

}

va_end(ap);              //结束从可变参数列表中获取参数

return sum;

}

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

{

int value1;

value1 = cal_val(1,2,3,4,5,6,7,8,9,0);

printf("value1=%d/n",value1);

value2 = cal_val(6,7,8,9,0);

printf("value2=%d/n",value2);

return 0;

}

C99就支持可变参数宏 ,两种写法:

#define   dbgprint(format,args...)   \

fprintf(stderr,   format,   ##args)

#define   dgbmsg(fmt,...)   \

printf(fmt,__VA_ARGS__)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值