[转]printf 函数实现的深入剖析

研究printf的实现,,首先来看看printf函数的函数体 int printf(const char *fmt, …){int i;char buf[256];         va_list arg = (va_list)((char*)(&fmt) + 4);     i = vsprintf(buf, fmt, arg);     write(buf, i);         return i;    }    代码位置:D:/~/funny/kernel/printf.c        在形参列表里有这么一个token:…    这个是可变形参的一种写法。    当传递参数的个数不确定时,就可以用这种方式来表示。    很显然,我们需要一种方法,来让函数体可以知道具体调用时参数的个数。        先来看printf函数的内容:        这句:        va_list arg = (va_list)((char*)(&fmt) + 4);        va_list的定义:    typedef char *va_list    这说明它是一个字符指针。    其中的: (char*)(&fmt) + 4) 表示的是…中的第一个参数。    如果不懂,我再慢慢的解释:    C语言中,参数压栈的方向是从右往左。    也就是说,当调用printf函数的适合,先是最右边的参数入栈。    fmt是一个指针,这个指针指向第一个const参数(const char *fmt)中的第一个元素。    fmt也是个变量,它的位置,是在栈上分配的,它也有地址。    对于一个char *类型的变量,它入栈的是指针,而不是这个char *型变量。    换句话说:    你sizeof(p) (p是一个指针,假设p=&i,i为任何类型的变量都可以)    得到的都是一个固定的值。(我的计算机中都是得到的4)    当然,我还要补充的一点是:栈是从高地址向低地址方向增长的。    ok!    现在我想你该明白了:为什么说(char*)(&fmt) + 4) 表示的是…中的第一个参数的地址。        下面我们来看看下一句:     i = vsprintf(buf, fmt, arg);        让我们来看看vsprintf(buf, fmt, arg)是什么函数。          

int vsprintf(char *buf, const char *fmt, va_list args) { char* p; char tmp[256]; va_list p_next_arg = args; for (p=buf;*fmt;fmt++) { if (*fmt != ‘%’) { *p++ = *fmt; continue; } fmt++; switch (*fmt) { case ‘x’: itoa(tmp, *((int*)p_next_arg)); strcpy(p, tmp); p_next_arg += 4; p += strlen(tmp); break; case ‘s’: break; default: break; } } return (p – buf); } 伟人所达到并保持着的高处,并不是一飞就到的,

[转]printf 函数实现的深入剖析

相关文章:

你感兴趣的文章:

标签云: