实现自己的printf打印 -- 可变参数的函数

  /*X86平台,参数传递是基于堆栈来完成的,对内存使用时连续的*/ 
    void printf_myself(const char *format, ...)
    {
    	/*char *ptr_s = &format;*/
    	int num; char ch; double d;
    	struct _student stu;
    	/*const char *name_str;*/
    	/*指针操作,1取值,2指针自增(移动指针)*/
    	/*char *s = format; // char *s = **ptr_s;*/
    
    	va_list p;
    	
    	printf("str = %s\n", format);	
    	
    	va_start(p,format); //取指针变量的值(不是所指向的值),并将指针p自增
    	
    	num = va_arg(p,int); // 取值 并 移动指针
    	printf("num = %d\n", num);
    	
        stu = va_arg(p,struct _student);
    	printf("stu.num  = %d\n", stu.num);
    	printf("stu.name = %s\n", stu.name);
    	printf("stu.age  = %d\n", stu.age);
    	
        num = va_arg(p,int);
    	printf("num = %d\n", num);
    
        ch = va_arg(p,int);
    	printf("ch = %c\n", ch);
    	
        d = va_arg(p,double);
    	printf("num = %f\n", d);
    	va_end(p);
    }

其实实现可变参数列表是如此的简单,哈哈,
一句话来概括就是:
/X86平台,参数传递是基于堆栈来完成的,对内存使用时连续的/

三步走!!!
1,取指针变量的值(不是所指向的值)

va_list p; //va_list 是一个字符指针变量的宏 typedef char * va_list;
va_start(p,format);
这个操作将会取首地址,并使得指针p自增format位

2,取值 并 移动指针
num = va_arg(p,int);

va_arg()这个宏用来取出指针移动后所指向的地址的值,并移动p指针并以int类型移动指向,所以这里是移动4个字节。

va_end§;
最后这句是把p指向了一个空指针,防止野指针。

参考:
INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍 (除4取整):

define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) 
//这里 &上~(sizeof(int) - 1),也就是&上3取反,意思是清0掉低两位(相当于除4取整),因为没有用到系统或库函数实现的软件除法 所以才这么用
//另外 加 “+ sizeof(int) - 1” 是为了向上取整

VA_START宏,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数):

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

VA_ARG宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型):

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

VA_END宏,清空va_list可变参数列表:

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

最后,欢迎留言讨论,请多多指教!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值