C/C++ 变参函数详解
1. 简介
调用函数的实现原理是:执行跳转+参数传递。执行跳转,所有的CPU都提供跳转指令;参数传递,CPU会提供多种方式,最常见的是使用栈来传递参数。
2. 变参函数示列
头文件 #include <stdarg.h>
void f2(char* fmt, ...)
{
va_listap;
va_start(ap, fmt);
char*p = fmt;
while(*p) {
if(*p == '%'&& *(p+1) == 'd') {
printf("参数类型为int,值为%d\n", va_arg(ap, int));
}
elseif (*p == '%' && *(p+1)== 'f') {
printf("参数类型为double,值为%f\n", va_arg(ap, double));
}
elseif (*p == '%' && *(p+1)== 's') {
printf("参数类型为char*,值为%s\n", va_arg(ap, char*));
}
p++;
}
va_end(ap);
}
typedef struct BLKONEGROUPTAGFLAG
{
boolbTagIn;
boolbTagOut;
boolbTagValue;
boolbTagPoint;
int nValueSize;
int nPointInSize;
int nPointOutSize;
}BLKONEGROUPTAG;
// "in,v,4;in,p,%d"
void Serialize(char* fmt, ...)
{
va_listap; // 定义一个变参函数列表变量
va_start(ap, fmt); // 将变量初始化指向变参函数
char*pszCurrFmt = newchar(strlen(fmt)+1);
strcpy_s(pszCurrFmt, strlen(fmt)+1, fmt);
char*pRes = pszCurrFmt;
char*pRet = NULL;
char*pszContext = NULL;
boolbTagIn = false;
while( pRet = strtok_s(pRes, ";", &pszContext))
{
BLKONEGROUPTAGblkOneGruop;
memset(&blkOneGruop, 0, sizeof(BLKONEGROUPTAG));
char*pRes2 = pRet;
char*pszContext2 = NULL;
while( pRet = strtok_s(pRes2, ",", &pszContext2))
{
char*p = pRet;
if( *p == 'i'&& *(p+1) == 'n' )
{
blkOneGruop.bTagIn = true;
}
elseif ( *p == 'o' && *(p+1)== 'u' && *(p+2)== 't' )
{
blkOneGruop.bTagOut = true;
}
elseif ( *p == 'v' )
{
blkOneGruop.bTagValue = true;
}
elseif ( *p == 'p' )
{
blkOneGruop.bTagPoint = true;
}
else
{
if ( true == blkOneGruop.bTagIn&& true == blkOneGruop.bTagOut && true== blkOneGruop.bTagPoint)
{
blkOneGruop.nPointInSize= atoi(p);
}
else if ( true== blkOneGruop.bTagOut&& true == blkOneGruop.bTagPoint )
{
blkOneGruop.nPointOutSize= atoi(p);
}
else if ( true== blkOneGruop.bTagIn&& true == blkOneGruop.bTagPoint )
{
blkOneGruop.nPointInSize= atoi(p);
}
else if ( true== blkOneGruop.bTagIn)
{
blkOneGruop.nValueSize= atoi(p);
}
}
pRes2= NULL;
}
//解析结构体
void*pvParam = NULL;
char*pszData = NULL;
if( true == blkOneGruop.bTagPoint && true== blkOneGruop.bTagIn)
{
pvParam= va_arg(ap,void*); // 传进来的是什么,取出来的就是什么
pszData= (char*)(*(void**)pvParam);
}
elseif ( true == blkOneGruop.bTagPoint&& true == blkOneGruop.bTagOut )
{
pvParam= va_arg(ap,void*);
}
pRes= NULL;
}
va_end(ap);
}
int main()
{
// 测试
f2("%d,%f,%s", 100, 1.23, "hello world");
getchar();
char*psz = NULL;
char*pszIn = "123";
Serialize("in,v,4;in,p,64;out,p,32", &pszIn,&psz);
getchar();
return0;
}
附录:参考资料
https://blog.csdn.net/smstong/article/details/50751121