C库<stdarg.h>实现可变参函数

来源:互联网 发布:守望网络初始化失败bo 编辑:程序博客网 时间:2024/05/17 07:29
我们都知道C++里的函数有重载功能,对同名函数可以传入不同类型或个数的参数,实现不同的功能。这些参数类型和个数必须在函数定义时确定的,编译器会根据参数列表格式,调用相应的函数。
但是,如果我们在调用之前根本不知道到底要调用几个参数,不知道参数类型,怎么办???

变参函数:
   int func(int n, …); 
注:C中最左边第一个参数必须确定,而C++里则可以省略
如C++中自定义log打印函数:
#define ALOGV(…)   ((void)(ALOG(LOG_VERBOSE,LOG_TAG,__VA_ARGS__))
#ifndef ALOG
#define ALOG(priority, tag, …)   LOG_PRI(ANDROID##priority, tag, __VA_ARGS__)
#endif 


对于func(int x, float y, double z);最后一个参数z先入栈,栈底是低地址,栈顶是高地址。那么在函数调用时,z先进栈,最后是x。对于此方式必须确切知道调用函数的参数类型,才能准确的计算参数列表的实际长度。


下面是网上找的关于输出log信息到屏幕的例子:

<span style="font-family:Arial;">#include <stdarg.h>#include <stdio.h>#include <string.h>void my_printf(char *ft, ...){char *p = ft;int tmp_i;char *tmp_s;double tmp_f;va_list ap;   //va_list是一个字符指针,指向当前参数的指针,取参数通过该指针进行va_start(ap,ft);  //对ap进行初始化,使其指向参数列表里的第一个参数while(*p){if(*p != '%'){putchar(*p++); //如果不是%,则将该字符在终端输出continue;}else{switch(*++p){case 'd':{tmp_i = va_arg(ap,int);printf("%d",tmp_i);break;}case 'c':{tmp_i = va_arg(ap,int);  //char在内部提升为intprintf("%d",tmp_i);break;}case 's':{//tmp_s = va_arg(ap,char*);for(tmp_s=va_arg(ap,char *);*tmp_s;tmp_s++)printf("%c",*tmp_s);break;}case 'f':{tmp_f = va_arg(ap,double); //float在内部被提升为doubleprintf("%f",tmp_f);    break;}}// end switch}p++;}//end while()va_end(ap);}int main(){int a= 10;float b = 3.14;char* c = "abcdeffsaf";my_printf("my_print the int [%d], the float [%f], the string [%s]",a,b,c);return 1;}</span>


0 0
原创粉丝点击