C语言面试题---函数(二)
来源:互联网 发布:java 汉字转数字 编辑:程序博客网 时间:2024/06/05 18:22
原创2017-12-25创新教育研究中心TeachPlus
C语言面试题----函数(二)
c语言中,跟函数相关的考题,偶尔还会出现与变长参数相关的问题。
在C语言编程中有时会遇到一些参数个数可变的函数,例如 printf(),scanf() 函数,
查看man手册时其函数原型为:
int printf(const char* format,…);int scanf(const char *format,…);
它除了有一个参数format固定以外,后面跟着的参数的个数和类型是可变的(用三个点“…”做参数
占位符),实际调用时可以有以下的形式:
printf(“%d”,i);printf(“%d,%c”,i,j);
这就是所谓参数可变的函数。
C语言用 va_start 等宏来处理这些可变参数。这些宏看起来很复杂,其实原理挺简单,
就是根据参数入栈的特点从最靠近第一个可变参数的固定参数开始,依次获取每个可变参数的地址。
在标准C语言中定义了一个头文件 <stdarg.h> 专门用来对付可变参数列表,它
包含了一组宏,和一个 va_list 的 typedef 声明。来看一个例子:
# include <stdio.h># include <stdarg.h># include <stdlib.h>void test( int num ,...);int main(){ test(5,3,5,2,0,3); return 0;}void test( int num,...){ va_list ap; va_start(ap,num); int i = 0; for(i = 0 ; i < num; i++) { printf("%d\n",va_arg(ap, int)); sleep(1); } va_end(ap);}
函数输出为:
3
5
2
0
3
5
2
0
3
在本例中,首先包含了 <stdarg.h> 头文件,处理不定长参数的宏全部定义在这里面,
所以用到可变参数的程序应该包含这个头文件.
然后声明了不定长参数函数 test() ,这里需要注意的是,所以为的不定长参数列列表,
只是指 ... 代表的部分,前面的 int num 不属于不定长参数列表。
然后在函数中,首先定义了 va_list 类型的 ap ,这个变量是指向参数地址的指针.
因为得到参数的地址之后,再结合参数的类型,才能得到参数的值。
再然后用 va_start 宏初始化上一步中定义的变量 ap ,这个宏的第二个参数是可变
参数列表的前一个参数,也就是最后一个固定参数。在本例中就是 int num 。
然后依次用 va_arg 宏使 ap 返回可变参数的地址,得到这个地址之后,结合参数的类型,
就可以得到参数的值。然后进行输出。
可变参数用到以下宏函数:
<1>原型: void va_start(va_list arg_ptr,prev_param);
功能:以固定参数的地址为起点确定变参的内存起始地址,获取第一个参数的首地址
返回值:无<2>原型: va_list 类型的变量, va_list ap ,这个变量是指向参数地址的指针,
因为得到参数的地址之后,再结合参数的类型,才能得到参数的值。
<3>原型: type va_arg(va_list arg_ptr,type);
功能:获取下一个参数的地址
返回值:根据传入参数类型决定返回值类型
<4>原型: void va_end(va_list arg_ptr);
功能:将arg_ptr指针置0
返回值:无
最后一道题目巩固一下,利用变长参数输出不定长字符串
答案:
# include <stdio.h>
# include <stdarg.h>void PrintLines( char *first,...){ char *str; va_list v1; str = first; va_start(v1,first); do { printf("%s\n",str); str=va_arg(v1, char*); }while (str != NULL ); va_end(v1);}int main( int argc, char* argv[]){ PrintLines("First","Second","Third","Fourth",NULL); return 0;}
阅读全文