函数的代码是在编译时候生成的,对于带有不定参数个数(甚至对于每一个参数对应的类型也不也一样)的函数,编译器怎么在支持这样的函数。
#include < stdio.h>
#include < string.h>
#include < stdarg.h>
/* 函数原型声明,至少需要一个确定的参数,注意括号内的省略号 */
int demo( char *, ...) ;
void main( void )
{
demo("DEMO"," This"," is "," a ","demo!", "\0");
}
int demo( char *msg, ... )
{
va_list argp; /* 定义保存函数参数的结构 */
int argno = 0; /* 纪录参数个数 */
char *para; /* 存放取出的字符串参数 */
va_start( argp, msg );
while (1)
{
para = va_arg( argp, char *);
if ( strcmp( para, "\0" ) == 0 ) /* 采用空串指示参数输入结束 */
break;
printf("参数 #%d 是: %s\n", argno, para);
argno++;
}
va_end( argp ); /* 将argp置为NULL */
return 0;
}
有意思是介绍几个宏
先看这个:
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
这个是为了内存对齐,可以将n这个类型长度转换为sizeof(int)的倍数长度。 比如sizeof (n)=9 ,sizeof(int)=4,
那么 _INTSIZEOF(n) = ( 9 + 4 -1)&~(4 -1) = 12/3 = 4. 也就是将 9 转换为 12,为边界对齐加了一个3.
关一个这个的证明在这:
蛮经典的:http://blogold.chinaunix.net/u/1129/showart_397677.html
//#define va_start _crt_va_start
//#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
//#define _ADDRESSOF(v) ( &reinterpret_cast<const char &>(v) )
//#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
//#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
NOTE:
1.从va_start宏依赖第一个函数地址,得到下一个函数的地址。这也就是为什么不定参数的函数需要至少一个参数。
2.对于函数参数的个数的判读,需要自己。如果printf里面第一个参数定义可以得到后面的参数个数,或者最后一个参数要有定义。
3.封装一个在VC下常用的不定参数调试输出函数
void PrintMsg(char* fmt, ...){
char* buf=new char[1024];
va_list args;
va_start(args,fmt);
vsprintf_s(buf,1024, fmt, args);
va_end(args);
OutputDebugString(buf);
free(buf);
return;
}
//适用于C语言
#define MyPrintf(fmt,args...) do{\
time_t timep;struct tm *pt;char timeStr[28];\
time (&timep);pt=gmtime(&timep);\
sprintf(timeStr,"[%02d:%02d:%02d]",(pt->tm_hour+8)%24,pt->tm_min,pt->tm_sec);\
printf("%s "fmt"\n",timeStr,##args);\
}while(0)
//适用于C++
#define println(format,...) \
{ \
printf("[%llu] (%s:%d):",GetTickCount(),__FUNCTION__, __LINE__); \
printf(format,__VA_ARGS__); \
printf("\n"); \
}
//debug和release模式下都能输出信息,如: PrintMsg("%s-Number:%d\n","Test",1234);