从va_list、va_start、va_arg、va_end想到了vsprintf的源码
来源:互联网 发布:mac移动硬盘无法分区 编辑:程序博客网 时间:2024/05/19 02:45
在前面的博文中, 我彻谈了从va_list、va_start、va_arg、va_end的用法, 但是, 当我看到某个程序后, 非常纳闷, 于是迫不及待得想知道vsprintf的实现。
在我的第一印象中, vsprintf貌似和vs有关, 也就是和微软有关, 所以懒得去管微软那些东东, 其实, vsprintf和微软没有毛关系, linux也有这个东东,而v是variable的缩写。 看来, 是我误解vsprintf了。
我们先看看这段代码(我之前写的):
#include <iostream>#include <string>#include <fstream>#include <cstdarg>using namespace std;void log(const char *format, ...){va_list args;va_start(args, format);char buf[4096] = {0};vsprintf(buf, format, args);va_end(args);ofstream outfile("log.txt", ios::app);outfile << buf << endl;}int main(){log("%s%d, %s%d", "practice", 1, "practice", 2);return 0;}看到vsprintf那一行, 只用了args, 没有用av_arg啊, 这就必然要求vsprintf中利用args和av_arg, 而且会遍历变参, 并利用format(依赖于其中的格式化字符串进而对变参进行解析), 这是必然的。
我都不知道该说点什么了, 还是迫不及待地看看vsprintf的源码吧(最后一个参数的类型是va_list):
int vsprintf(char *buf, const char *fmt, va_list args){ char *str, *s; int base; int flags = 0; int fildwidth = -1; int precision = -1; int qualifier; unsigned long num; for(str = buf; *fmt != '\0'; fmt++) { if(*fmt == '\t') { int k = 8; while(k--) *str++ = ' '; fmt++; } if(*fmt != '%') { *str++ = *fmt; continue; }handle_flags: fmt++; switch (*fmt) { case '#': flags |= PREFIX; goto handle_flags; } /* handle_fldwidth: */ /* don't need this now */ /* handle_precision: */ /* don't need this now */ /* handle_lenmodifier: */ /* don't need this now */ /* handle_qualifier: */ qualifier = -1; if(*fmt == 'l' || *fmt == 'L' || *fmt == 'h') { qualifier = *fmt; fmt++; } /* handle_convtype: */ base = 10; switch(*fmt) { case 'c': /* processing alignment */ *str = (unsigned char)va_arg(args, int); /* processing alignment */ continue; case 's': s = va_arg(args, char *); str = strcpy(str, s); /* is it safe? */ str--; continue; case 'd': break; case 'o': base = 8; break; case 'x': flags |= SMALL; case 'X': base = 16; break; default: *str++ = '%'; if(*fmt) *str++ = *fmt; else fmt--; continue; } if (qualifier == 'l') num = va_arg(args, unsigned long); else if (qualifier == 'h') num = (unsigned short)va_arg(args, int); else { num = va_arg(args, int); } str = num2str(str, num, base, fildwidth, precision, flags); } *str = '\0'; return str - buf;}再来看看我们最常用的printf的实现吧, 很俗套了:
int printf(const char *fmt, ...){ char buf[1024]; va_list args; int cnt; va_start(args, fmt); cnt = vsprintf(buf, fmt, args); va_end(args); putstr(buf); return cnt;}不多说。
0 0
- 从va_list、va_start、va_arg、va_end想到了vsprintf的源码
- VA_LIST VA_START VA_ARG VA_END
- va_list、va_start、va_arg、va_end
- va_list va_start va_arg va_end
- va_list、va_start、va_arg、va_end
- va_list, va_start, va_end, va_arg
- va_list、va_start、va_arg、va_end
- va_list & va_start & va_arg & va_end
- va_list、va_start、va_arg、va_end
- va_list/va_start/va_arg/va_end
- va_start/va_arg/va_end/va_list
- 宏:va_list、va_start、va_arg、va_end的使用
- 宏:va_list、va_start、va_arg、va_end的使用
- va_list、va_start、va_arg、va_end宏的学习
- va_list,va_start,va_arg,va_end的效率
- va_list、va_start、va_arg、va_end宏的使用方法
- va_start、va_end、va_list、va_arg的使用整理
- va_list、va_start、va_arg、va_end宏的使用
- 关于IT公司招聘的一个思考
- Selinux SeAndroid理解
- Unity调用Android API
- ios pickerView 点菜
- 每周小结-3 D3 on AngularJS
- 从va_list、va_start、va_arg、va_end想到了vsprintf的源码
- PHP入门学习笔记之—— 分享 PHP 理论+实践学习网站
- OC阅读笔记十八:僵尸对象(Zombie Object)
- POJ2151 : Check the difficulty of problems
- 工作四年的迷茫
- Apache James配置个人笔记(完整解决DNS问题), 网页版的参考 Claros In Touch webmail(Pop3/IMAP)
- 数据库1
- 数组去重
- View绘制流程(3)----view的绘制流程及自定义View的相关问题