这一篇是对韦东山2440的uart的printf课程的总结。printf是c标准库stdio.h的函数,本来想要把它移植在裸板上,存储是不够的。但是,作为一个能直接打印信息的函数,对调试很有用。所以,就对它进行一些操作。
仿照printf的几个难点在于:
1-printf函数的参数,是有一个char *的常量字符串和若干变参变量构成。怎么从char *这一个常量里,读取出哪里是要替换为那些参数的。(这个在代码里解决)
2-这些参数,怎么确定是什么变量类型,特别是对于结构体,怎么知道结构体里有什么变量类型。(这个并没有解决,所以要避开)
3-这些变量的地址在哪里,然后才能去获得它们的值。(这个在下面文字里解决)
4-像int这种类型,打印出来本质上是打印的是形式上是数据的字符串,这一步的转换也要考虑到。(这个在代码里解决)
以下就是从这些问题解决。
printf函数的参数,是有一个char *的常量字符串和若干变参变量构成。对于函数来说,背后的机制是,函数传入的参数是进入了堆栈,先进后出。而且这些参数的地址是连续的(大小就同sizeof(变量类型))。
所以,对于变参变量来说,只要知道它们的首地址,就可以知道所有的变量的地址,并读取出对应的值。
首地址,本质的做法,就是取 那个char *的常量字符串(一般称为,format)的地址。对于后面的变量参数地址,就是,char *的地址,加上sizeof(变量类型),如此反复叠加则可。
不过c语言提供了包装了上面取地址,移动指针的几个函数。
va_list p; | 定义一个变参变量p,相当于char * |
va_start(p,fmt ); | format是固定参数,经过va_start(p,format),p移动到第一个变参变量 |
va_arg( p, 变量类型); | 在已知变量类型前提下,通过这个函数,将目前地址的所指向的值以这个变量类型返回,并自动加上siz |