C语言中传递函数参数时的用法和原理:
1.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表
2.函数参数的传递原理
函数参数是以数据结构:栈的形式存取,从右至左入栈。
<span style="white-space:pre"> </span>typedef char* va_list; void va_start ( va_list ap, prev_param ); /* ANSI version */ type va_arg ( va_list ap, type ); void va_end ( va_list ap ); #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址 #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址 #define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效
#include <iostream.h> void fun(int a, ...) { int *temp = &a; temp++; for (int i = 0; i < a; ++i) { cout << *temp << endl; temp++; } } int main() { int a = 1; int b = 2; int c = 3; int d = 4; fun(4, a, b, c, d); system("pause"); return 0; }
Output::
1
2
3
4
</pre><pre name="code" class="cpp">void TestFun(char* pszDest, int DestLen, const char* pszFormat, ...) { <span style="white-space:pre"> </span>va_list args; <span style="white-space:pre"> </span>va_start(args, pszFormat); //一定要“...”之前的那个参数 <span style="white-space:pre"> </span>_vsnprintf(pszDest, DestLen, pszFormat, args); <span style="white-space:pre"> </span>va_end(args); }
#include 〈stdio.h〉 #include 〈string.h〉 #include 〈stdarg.h〉 /*函数原型声明,至少需要一个确定的参数,注意括号内的省略号*/ int demo( char, ... ); void main( void ) { demo("DEMO", "This", "is", "a", "demo!", ""); } /*ANSI标准形式的声明方式,括号内的省略号表示可选参数*/ int demo( char msg, ... ) { /*定义保存函数参数的结构*/ va_list argp; int argno = 0; char para; /*argp指向传入的第一个可选参数,msg是最后一个确定的参数*/ va_start( argp, msg ); while (1) { para = va_arg( argp, char); if ( strcmp( para, "") == 0 ) break; printf("Parameter #%d is: %s\n", argno, para); argno++; } va_end( argp ); /*将argp置为NULL*/ return 0; }
<div class="para" style="color: rgb(51, 51, 51); margin: 15px 0px 5px; text-indent: 2em; line-height: 24px; font-family: arial, 宋体, sans-serif; font-size: 14px;"></div><pre name="code" class="cpp">void arg_test(int i, ...); int main(int argc,char *argv[]) { <span style="white-space:pre"> </span>int int_size = _INTSIZEOF(int); <span style="white-space:pre"> </span>printf("int_size=%d\n", int_size); <span style="white-space:pre"> </span>arg_test(0, 4); <span style="white-space:pre"> </span>//arg_cnt(4,1,2,3,4); <span style="white-space:pre"> </span>return 0; } void arg_test(int i, ...) { <span style="white-space:pre"> </span>int j=0; <span style="white-space:pre"> </span>va_list arg_ptr; <span style="white-space:pre"> </span>va_start(arg_ptr, i); <span style="white-space:pre"> </span>printf("&i = %p\n", &i);//打印参数i在堆栈中的地址 <span style="white-space:pre"> </span>printf("arg_ptr = %p\n", arg_ptr);//打印va_start之后arg_ptr地址 <span style="white-space:pre"> </span>/*这时arg_ptr应该比参数i的地址高sizeof(int)个字节,即指向下一个参数的地址*/ <span style="white-space:pre"> </span>j=*((int *)arg_ptr); <span style="white-space:pre"> </span>printf("%d %d\n", i, j); <span style="white-space:pre"> </span>j=va_arg(arg_ptr, int); <span style="white-space:pre"> </span>printf("arg_ptr = %p\n", arg_ptr);//打印va_arg后arg_ptr的地址 <span style="white-space:pre"> </span>/*这时arg_ptr应该比参数i的地址高sizeof(int)个字节,即指向下一个参数的地址,如果已经是最后一个参数,arg_ptr会为NULL*/ <span style="white-space:pre"> </span>va_end(arg_ptr); <span style="white-space:pre"> </span>printf("%d %d\n", i, j); }
转载地址:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html
http://baike.baidu.com/view/2923501.htm?fr=aladdin