变长参数列表
时间:2010-04-06 来源:light511
这里有一个陷阱需要避免:
va_arg宏的第2个参数不能被指定为char、short或者float类型。
因为char和short类型的参数会被转换为int类型,而float类型的参数会被转换为double类型 ……
例如,这样写肯定是不对的:
c = va_arg(ap,char);
因为我们无法传递一个char类型参数,如果传递了,它将会被自动转化为int类型。上面的式子应该写成:
c = va_arg(ap,int);
——《C陷阱与缺陷》p164
在C语言中,调用一个不带原型声明的函数时:
调用者会对每个参数执行“默认实际参数提升(default argument promotions)”。
#include<stdlib.h> #include<stdarg.h> int writelog(char * first,...)
{
//该日志函数的参数只处理5种常用的数据类型:int (%d) , unsigned int (%u), char(%c), char * (%s), float (%f)
int i=0,flag=0;
int const SIZE=1024;
char tmp1[1024]={'\0'};
char tmp2[1024]={'\0'};
char *pf=first;
char *ps=first;
char * tt ;
va_list marker;
FILE *cfptr; va_start( marker, first );
printf("first=%s\n",first);
strcpy(tmp2,"LOG... ");
while((ps-first)<strlen(first))
{
pf=ps;
if((ps=strstr(pf,"%"))!=NULL)
{
ps++;
switch( *ps )
{
case 'd':
{
flag=1;
memset(tmp1,'\0',SIZE);
memcpy(tmp1,pf,ps-pf-1);
strcat(tmp2,tmp1);
ps++;
memset(tmp1,'\0',SIZE);
sprintf(tmp1,"%d",va_arg( marker, int));
strcat(tmp2,tmp1);
break;
}
case 'u':
{
flag=1;
memset(tmp1,'\0',SIZE);
memcpy(tmp1,pf,ps-pf-1);
strcat(tmp2,tmp1);
ps++;
memset(tmp1,'\0',SIZE);
sprintf(tmp1,"%u",va_arg( marker,unsigned int));
strcat(tmp2,tmp1);
break;
}
case 'c':
{
flag=1;
memset(tmp1,'\0',SIZE);
memcpy(tmp1,pf,ps-pf-1);
strcat(tmp2,tmp1);
ps++;
memset(tmp1,'\0',SIZE);
sprintf(tmp1,"%c",va_arg( marker, int));
strcat(tmp2,tmp1);
break;
}
case 's':
{
flag=1;
memset(tmp1,'\0',SIZE);
memcpy(tmp1,pf,ps-pf-1);
strcat(tmp2,tmp1);
ps++;
memset(tmp1,'\0',SIZE);
tt =va_arg( marker, char*);
strcpy(tmp1,tt);
strcat(tmp2,tmp1);
break;
}
case 'f':
{
flag=1;
memset(tmp1,'\0',SIZE);
memcpy(tmp1,pf,ps-pf-1);
strcat(tmp2,tmp1);
ps++;
memset(tmp1,'\0',SIZE);
sprintf(tmp1,"%lf",va_arg( marker, double));
strcat(tmp2,tmp1);
break;
}
default:
{ memset(tmp1,'\0',SIZE); strcat(tmp1,pf); strcat(tmp2,tmp1);
break;
}
}
}
else { break; }
}
if(!flag)
{
strcat(tmp2,first);
}
strcat(tmp2,"\n");
printf("%s\n",tmp2);
if((cfptr=fopen("D:\\handlerlog.txt","a+"))!=NULL)
{
fputs(tmp2,cfptr);
fclose(cfptr);
}
else
{
printf("file cann't be opened!");
}
va_end( marker );
return 0;
} int main(int argc,char ** argv)
{ char path[10]="good";
int x=180;
unsigned int y=360;
float z=3.14;
writelog("第%u个的名字是: %s\n",y,path);
writelog("%c\n",'k'); return 0; }
va_arg宏的第2个参数不能被指定为char、short或者float类型。
因为char和short类型的参数会被转换为int类型,而float类型的参数会被转换为double类型 ……
例如,这样写肯定是不对的:
c = va_arg(ap,char);
因为我们无法传递一个char类型参数,如果传递了,它将会被自动转化为int类型。上面的式子应该写成:
c = va_arg(ap,int);
——《C陷阱与缺陷》p164
在C语言中,调用一个不带原型声明的函数时:
调用者会对每个参数执行“默认实际参数提升(default argument promotions)”。
同时,对可变长参数列表超出最后一个有类型声明的形式参数之后的每一个实际参数,也将执行上述提升工作。
提升工作如下:
——float类型的实际参数将提升到double
——char、short和相应的signed、unsigned类型的实际参数提升到int
——如果int不能存储原值,则提升到unsigned int
然后,调用者将提升后的参数传递给被调用者。
#include<stdlib.h> #include<stdarg.h> int writelog(char * first,...)
{
//该日志函数的参数只处理5种常用的数据类型:int (%d) , unsigned int (%u), char(%c), char * (%s), float (%f)
int i=0,flag=0;
int const SIZE=1024;
char tmp1[1024]={'\0'};
char tmp2[1024]={'\0'};
char *pf=first;
char *ps=first;
char * tt ;
va_list marker;
FILE *cfptr; va_start( marker, first );
printf("first=%s\n",first);
strcpy(tmp2,"LOG... ");
while((ps-first)<strlen(first))
{
pf=ps;
if((ps=strstr(pf,"%"))!=NULL)
{
ps++;
switch( *ps )
{
case 'd':
{
flag=1;
memset(tmp1,'\0',SIZE);
memcpy(tmp1,pf,ps-pf-1);
strcat(tmp2,tmp1);
ps++;
memset(tmp1,'\0',SIZE);
sprintf(tmp1,"%d",va_arg( marker, int));
strcat(tmp2,tmp1);
break;
}
case 'u':
{
flag=1;
memset(tmp1,'\0',SIZE);
memcpy(tmp1,pf,ps-pf-1);
strcat(tmp2,tmp1);
ps++;
memset(tmp1,'\0',SIZE);
sprintf(tmp1,"%u",va_arg( marker,unsigned int));
strcat(tmp2,tmp1);
break;
}
case 'c':
{
flag=1;
memset(tmp1,'\0',SIZE);
memcpy(tmp1,pf,ps-pf-1);
strcat(tmp2,tmp1);
ps++;
memset(tmp1,'\0',SIZE);
sprintf(tmp1,"%c",va_arg( marker, int));
strcat(tmp2,tmp1);
break;
}
case 's':
{
flag=1;
memset(tmp1,'\0',SIZE);
memcpy(tmp1,pf,ps-pf-1);
strcat(tmp2,tmp1);
ps++;
memset(tmp1,'\0',SIZE);
tt =va_arg( marker, char*);
strcpy(tmp1,tt);
strcat(tmp2,tmp1);
break;
}
case 'f':
{
flag=1;
memset(tmp1,'\0',SIZE);
memcpy(tmp1,pf,ps-pf-1);
strcat(tmp2,tmp1);
ps++;
memset(tmp1,'\0',SIZE);
sprintf(tmp1,"%lf",va_arg( marker, double));
strcat(tmp2,tmp1);
break;
}
default:
{ memset(tmp1,'\0',SIZE); strcat(tmp1,pf); strcat(tmp2,tmp1);
break;
}
}
}
else { break; }
}
if(!flag)
{
strcat(tmp2,first);
}
strcat(tmp2,"\n");
printf("%s\n",tmp2);
if((cfptr=fopen("D:\\handlerlog.txt","a+"))!=NULL)
{
fputs(tmp2,cfptr);
fclose(cfptr);
}
else
{
printf("file cann't be opened!");
}
va_end( marker );
return 0;
} int main(int argc,char ** argv)
{ char path[10]="good";
int x=180;
unsigned int y=360;
float z=3.14;
writelog("第%u个的名字是: %s\n",y,path);
writelog("%c\n",'k'); return 0; }
相关阅读 更多 +