可变参列表

来源:互联网 发布:php 微信开发 编辑:程序博客网 时间:2024/06/02 01:53

在可变参数列表中,我们在没有对应的参数表示符时,如何获取参数列表,在可变参数列表中我们,只有"...",所以通过标示符得到是不可能的,于是我们只好寻找另一种方式去获取,我们知道函数在调用时都会返回地址,参数,等压入到分配的栈空间中。参数的入栈顺序会取决于你的调用约定,如stdcall cd call fastcall等等,因此其实参数的顺序是有顺序的,va_start(va_list va,last)我们可以通过last参数的地址,从而访问其他的参数.其实va_list 本质上只是char*类型

1)typedef char * va_list;_list 
2)#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
3)#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

将最后一个参数的地址加上可变参数对其便宜后赋值给ap,即可变参数的首地址
4)#define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

指向下一个参数的地址

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

#include <stdio.h>#include <stdarg.h>#include <string.h>void translate(va_list va,const char *cmd);void myprintf(const char *cmd,...);int main(){myprintf("%s %d %c %f\n","aa",14,'b',3.14);return 0;}void myprintf(const char *cmd,...){va_list va;va_start(va,cmd);translate(va,cmd);va_end(va);}void translate(va_list va,const char* cmd){if('\0' == *cmd)return;if('%' != *cmd){translate(va,cmd+1);}else{switch(*(cmd+1)){case 'd':case 'x':case 'c':{char buf[3] = "%";buf[1] = *(cmd+1);int value;value = va_arg(va,int);printf(buf,value);}break;case 'f':{double value = va_arg(va,double);printf("%f",value);}break;case 's':{char *value = va_arg(va,char*);printf("%s",value);}break;default:printf("%%");}translate(va,cmd+2);}}