我们将实现printf的模拟。在这之前,先总结可变参数列表的有关知识点~
在函数原型中,列出了函数期望的参数,但原型只能显示固定数目的参数。其实,让一个函数接收不同数目的参数也
是可以的。可变参数列表是通过宏来实现,这些宏定义于stdarg.h文件,它是标准库的一部分。这个头文件声明了一
个类型va_list和三个宏——va_start、va_arg、va_end.在编译器下,我们通过查看定义来理解和明白这些宏和类型
到底是表示什么。
VC6.0下对他们的定义如图所示~
va_list是char类型的指针~
va_start是用来初试化arg,找到未知参数的第一个参数的地址
va_arg是用于遍历未知参数的每个参数,每一次我们找一个参数时,arg指针都会指向该参数的下一个位置~所以我
们不要连着使用这个宏,比如,当我们要找参数的最大值时,应该讲参数保存起来,而不是比较完了之后发
现需 要这 个参数,再利用va_start来找,这样就会漏过一些参数~
va_end把arg赋值为空,这个是必须要进行的操作~
下面我们利用可变参数列表来实现printf函数的模拟~
void print(char *format, ...) { va_list arg; va_start(arg,format); char c; char *str; while (*format) { switch (*format) { case 'c': { c = va_arg(arg,char); putchar(c); }break; case 's': { str = va_arg(arg,char*); //puts(str); while (*str) { putchar(*str); str++; } }break; default: putchar(*format); }format++; } va_end(arg); } int main() { print("s ccc.\n","hello",'b','i','t'); system("pause"); return 0; }代码分析:函数实现中,使用switch,case语句比if,else能好一些,至少结构上更清晰一点~printf模拟实现并不
是真正的模拟,在库函数里printf的第一个参数是%s,%c等等这种,而我模拟实现时 ,默认看到s就是输出字符串
,要想完全模拟库函数,还需要利用字符串的知识完成~还有,在输出字符串时,不要使用puts函数一次打印出字
符串,因为puts在输出完一个字符串时,会自动输出一个回车,所以我们需要while循环一个字符一个字符的输
出。
可变参数的限制:
1.至少要有一个参数~要是没有的话,怎么找到后边参数的地址呀??~
2.宏无法判断参数个数~
3.宏无法判断参数类型~
4.如果va_arg指定了错误类型,后果比较严重~