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

1 #include < stdio.h>
2 #include < string.h>
3 #include < stdarg.h>
4
6 int t(...)
7 {
8   return 0;
9 }
10 /* 函数原型声明,至少需要一个确定的参数,注意括号内的省略号 */
11 int demo( char *, ...) ;
12
13
14 void main( void )
15
16 {
17 demo("DEMO"," This"," is "," a ","demo!", "\0");
18 }
19
20 int demo( char *msg, ... )
21 {
22 va_list argp; /* 定义保存函数参数的结构 */
23 int argno = 0; /* 纪录参数个数 */
24 char *para; /* 存放取出的字符串参数 */
25
26 va_start( argp, msg );
27 while (1)
28 {
29 para = va_arg( argp, char *);
30 if ( strcmp( para, "\0" ) == 0 ) /* 采用空串指示参数输入结束 */
31 break;
32
33 printf("参数 #%d 是: %s\n", argno, para);
34 argno++;
35 }
36 va_end( argp ); /* 将argp置为NULL */
37
38 return 0;
39 }

有意思是介绍几个宏

先看这个:

#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里面第一个参数定义可以得到后面的参数个数,或者最后一个参数要有定义。

posted on 2011-04-19 16:48  RocZhang  阅读(7895)  评论(0编辑  收藏  举报