最近我在研究驱动,看到了很多手机开发底层的源代码。各种指针,各种宏函数,我这才发现自己的C语言基础原来真的不牢靠。
看到有fun(a,...)这种用法,突然意识C语言中有可变参数这个使用法,而自己从来没有设计过而用的最多的有可变参数的就是printf()这个函数。
于是相对printf()这个库函数内部的实现方法大概的思考一下。下面一段printf()地球人都知道的用法。
int a =10; double b = 20.0; char *str = "Hello world"; printf("begin print\n"); printf("a=%d, b=%.3f, str=%s\n", a, b, str);
1.从printf()的使用方法来看,就是无论其可变的参数有多少个,printf的第一个参数总是一个字符串。而正是这第一个参数,
使得它可以确认后面还有有多少个参数尾随。而尾随的每个参数占用的栈空间大小又是通过第一个格式字符串确定的。然而printf到底是怎样取第一个参数后
2.然后网上查阅了一些printf()的源代码。从声明到实现,如下。
1 //acenv.h 2 typedef char *va_list; 3 #define _AUPBND (sizeof (acpi_native_int) - 1) 4 #define _ADNBND (sizeof (acpi_native_int)-1) 5 #define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND)))) 6 #define va_end(ap) (void) 0 7 #define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND)))) 8 //start.c 9 static char sprint_buf[1024]; 10 int printf(char *fmt, ...){ 11 va_list args; 12 int n; 13 va_start(args, fmt); 14 n = vsprintf(sprint_buf, fmt, args); 15 va_end(args); 16 write(stdout, sprint_buf, n); 17 return n;} 18 //unistd.h 19 static inline long write(int fd, const char *buf, off_t 20 count){ 21 return sys_write(fd, buf, count); 22 }
真正的参数个数以及格式的确定是在vsprintf搞定的了。由于vsprintf的代码比较复杂,也不是我们这里要讨论的重点,所以下面就不再列出了.
更加相似的参考资料文档
地址如下:http://wenku.baidu.com/view/86fa8c000740be1e650e9afb.html###
先写这么多。后续继续研究
有什么错误之处,请大家多多指正。