从va_list、va_start、va_arg、va_end想到了vsprintf的源码
2016-04-11 23:30
309 查看
在前面的博文中, 我彻谈了从va_list、va_start、va_arg、va_end的用法, 但是, 当我看到某个程序后, 非常纳闷, 于是迫不及待得想知道vsprintf的实现。
在我的第一印象中, vsprintf貌似和vs有关, 也就是和微软有关, 所以懒得去管微软那些东东, 其实, vsprintf和微软没有毛关系, linux也有这个东东,而v是variable的缩写。 看来, 是我误解vsprintf了。
我们先看看这段代码(我之前写的):
我都不知道该说点什么了, 还是迫不及待地看看vsprintf的源码吧(最后一个参数的类型是va_list):
在我的第一印象中, 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; }不多说。
相关文章推荐
- Java入门 第一季第七章 方法
- 【ZOJ 3929】Deque and Balls(普通dp)
- MSSQL数据库的一些基础知识
- ListView中pointToPosition()方法使用示例.
- [设计模式]——单例模式_doubleChecking
- hdu 1251 统计难题
- Qt入门(对话框)
- NYOJ95众数问题
- C++实验3
- 【AC自动机/fail树】BZOJ3172- [Tjoi2013]单词
- HTTPS详解
- Spring transaction propagation
- 杭电ACM 1002
- LeetCode 121 Best Time to Buy and Sell Stock
- C++第二次作业2
- 爆打团队 2016.04.11 站立会议
- vs开启/禁用随机基址
- 使用unittest.TestSuite组织执行用例
- leetcode
- div展现与收起效果(鼠标移入移出)