求指导C语言中可变参数宏的知识
void va_test(char* a, char* b, char* c, …)//省略了一些代码
va_start(ap, c);//此时ap应该指向c后面的第一个可变参数,为什么我用printf("%s", ap);输出不了,ap不是已经指向那个可变参数了吗?求详解!!!
#define va_start(ap, v) (ap = (va_list)&(v) + _INTSIZEOF(v))
&v对这个函数而言不就是二级指针吗?为什么用到二级指针,直接去v的地址加上v的内存大小不照样得到v后面一个参数的地址吗?而用二级指针的话我调试了还不是那个地址,疑惑!
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) 这句前面*(t *)有什么意义?先强制转成二级指针再转为一级指针的作用是什么?
[解决办法]
void va_test(char* a, char* b, char* c, …){
//1) //定义va_list指针(不定参数列表指针)
va_list vlist;
//2)//初始化va_list指针,(不定参数指针,让他指向最后一个确定参数)
va_start(vlist,c);
//3)//读取后面的各个函数参数,格式为,type x = va_arg(vlist,type) ; 例如:
int x =
va_arg(vlist,int);
//4) 结束使用不定参数函数参数
va_end(vlist);
}
&v对这个函数而言不就是二级指针吗?为什么用到二级指针,直接去v的地址加上v的内存大小不照样得到v后面一个参数的地址吗?而用二级指针的话我调试了还不是那个地址,疑惑!
typedef char * va_list;所以ap 是个 char 类型的指针
ap += _INTSIZEOF(t)//让 ap跳过当前参数,指向下一个参数。
(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))//跳过当前参数后,
(ap += _INTSIZEOF(t)) - _INTSIZEOF(t)的值,为
ap - _INTSIZEOF(t)
ap-_INTSIZEOF(t)是当前参数的地址,类型为
char *
(t *)(ap-_INTSIZEOF(t))
char *强制转换为
t *
*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))
ap += _INTSIZEOF(t) //让ap,加上认定的参数长度(t 类型的参数,在传递时候的长度),
(t*)(ap-_INTSIZEOF(t)) //这就是当前参数地址,这里看作t类型的参数地址,
(*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve arguments from the list.
After all arguments have been retrieved, va_end resets the pointer to NULL.
The UNIX System V macros, defined in VARARGS.H, operate somewhat differently:
Any required arguments to the function can be declared as parameters in the usual way.
The last (or only) parameter to the function represents the list of optional arguments. This parameter must be named va_alist (not to be confused with va_list, which is defined as the type of va_alist).
va_dcl appears after the function definition and before the opening left brace of the function. This macro is defined as a complete declaration of the va_alist parameter, including the terminating semicolon; therefore, no semicolon should follow va_dcl.
Within the function, va_start sets arg_ptr to the beginning of the list of optional arguments passed to the function. va_start must be used before va_arg is used for the first time. The argument arg_ptr must have va_list type.
va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve the arguments from the list.
After all arguments have been retrieved, va_end resets the pointer to NULL.
Example
/* VA.C: The program below illustrates passing a variable
* number of arguments using the following macros:
* va_start va_arg va_end
* va_list va_dcl (UNIX only)
*/
#include <stdio.h>
#define ANSI /* Comment out for UNIX version */
#ifdef ANSI /* ANSI compatible version */
#include <stdarg.h>
int average( int first, ... );
#else /* UNIX compatible version */
#include <varargs.h>
int average( va_list );
#endif
void main( void )
{
/* Call with 3 integers (-1 is used as terminator). */
printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );
/* Call with 4 integers. */
printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );
/* Call with just -1 terminator. */
printf( "Average is: %d\n", average( -1 ) );
}
/* Returns the average of a variable list of integers. */
#ifdef ANSI /* ANSI compatible version */
int average( int first, ... )
{
int count = 0, sum = 0, i = first;
va_list marker;
va_start( marker, first ); /* Initialize variable arguments. */
while( i != -1 )
{
sum += i;
count++;
i = va_arg( marker, int);
}
va_end( marker ); /* Reset variable arguments. */
return( sum ? (sum / count) : 0 );
}
#else /* UNIX compatible version must use old-style definition. */
int average( va_alist )
va_dcl
{
int i, count, sum;
va_list marker;
va_start( marker ); /* Initialize variable arguments. */
for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )
sum += i;
va_end( marker ); /* Reset variable arguments. */
return( sum ? (sum / count) : 0 );
}
#endif
Output
Average is: 3
Average is: 8
Average is: 0