大佬教程收集整理的这篇文章主要介绍了C可变参数的函数,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
要处理可变参数,需要用C标准库的va_list类型和va_start、va_arg、va_end宏,这些定义在stdarg.h头文件中。我们首先对照反汇编分析在@L_367_5@myprintf函数时这些参数的内存布局。
myprintf函数的参数布局
这些参数是从右向左依次压栈的,所以第一个参数靠近着栈顶,第三个参数靠近栈底。这些参数在内存中是连续存放的,每个参数都对齐到4字节边界。第一个和第三个参数都是指针类型,各占4个字节,虽然第二个参数只占一个字节,但为了使第三个参数对齐到4字节边界,所以第二个参数也占4个字节。现在给出一个stdarg.h的简单实现
这个头文件中的内部宏定义_Bnd(X,bnd)将类型或变量x的长度对齐到bnd+1字节的整数倍,例如_Bnd(char,3U)的值是4, _Bnd(int,3U)也是4。
在myprintf中定义的va_list ap;其实是一个指针,va_start(ap,format)使ap指向format参数的下一个参数,也就是指向上图中esp+4的位置。然后va_arg(ap,int)把第二个参数的值按int型取出来,同时使ap指向第三个参数,也就是指向上图中esp+8的位置。然后va_arg(ap,char *)把第三个参数的值按char *型取出来,同时使ap指向更高的地址。va_end(ap)在我们的简单实现中不起任何作用,在有些实现中可能把ap改写成无效值,C标准要求在函数返回前调用va_end。
如果把myprintf中的char ch = va_arg(ap,int);改成char ch = va_arg(ap,char);,用我们的简单实现是没有问题的。但如果改用libc提供的stdarg.h,在编译时会报错:
因此要求char型的可变参数必须按int型来取,这是为了与C标准一致。
从myprintf的例子可以理解printf的实现原理,printf函数根据第一个参数(格式化字符串)来确定后面有集合参数,分别是什么类型。
还有一种方法可以确定可变参数的个数,就是在参数列表的末尾传一个SenTinel,例如NULL。execl()就采用了这种方法确定参数的个数。
以上是大佬教程为你收集整理的C可变参数的函数全部内容,希望文章能够帮你解决C可变参数的函数所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。