C语言不定参数函数的实现

函数的代码是在编译时候生成的,对于带有不定参数个数(甚至对于每一个参数对应的类型也不也一样)的函数,编译器怎么在支持这样的函数。 

 #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);

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值