随想录(由自定义打印函数想到的)
来源:互联网 发布:编程的希望纪录片 编辑:程序博客网 时间:2024/05/18 00:56
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
在编写代码的时候我们都会自己重新定义一个打印函数,为什么要这样呢?我想主要原因还是为了定义其中的打印开关。如果打开了开关,我们当然可以看到很多的打印信息,但是如果不需要这些信息,我们就可以关上这些开关,所以一般的打印函数函数都是可以自己定义的。
#include <stdio.h>#include <windows.h>void XiaoxingPrintf(char* str, ...){char buffer[64];va_list va;va_start(va, str);vsprintf(buffer, str, va);va_end(va);printf("%s\n", buffer);}int main(int argc, char* argv[]){XiaoxingPrintf(" argc = %d, &argv = 0x%x\n", argc, &argc);return 1;}上面的这段代码其实也很平常,看上去没有什么特别之处,但是我们想知道,这个va究竟是个什么东西?不妨可以反汇编看一下,
7: void XiaoxingPrintf(char* str, ...)8: {0040D430 push ebp0040D431 mov ebp,esp0040D433 sub esp,84h0040D439 push ebx0040D43A push esi0040D43B push edi0040D43C lea edi,[ebp-84h]0040D442 mov ecx,21h0040D447 mov eax,0CCCCCCCCh0040D44C rep stos dword ptr [edi]9: char buffer[64];10: va_list va;11:12: va_start(va, str);0040D44E lea eax,[ebp+0Ch]0040D451 mov dword ptr [ebp-44h],eax13: vsprintf(buffer, str, va);0040D454 mov ecx,dword ptr [ebp-44h]0040D457 push ecx0040D458 mov edx,dword ptr [ebp+8]0040D45B push edx0040D45C lea eax,[ebp-40h]0040D45F push eax0040D460 call vsprintf (0040d750)0040D465 add esp,0Ch14: va_end(va);0040D468 mov dword ptr [ebp-44h],015:16: printf("%s\n", buffer);0040D46F lea ecx,[ebp-40h]0040D472 push ecx0040D473 push offset string "%s\n" (0042201c)0040D478 call printf (0040d850)0040D47D add esp,817: }0040D480 pop edi0040D481 pop esi0040D482 pop ebx0040D483 add esp,84h0040D489 cmp ebp,esp0040D48B call __chkesp (0040d710)0040D490 mov esp,ebp0040D492 pop ebp0040D493 ret上面的汇编代码很多,其实有用的信息并不多。首先我们看va_start这一句话,好像做的事情很简单,就是把ebp+0xc给了va,va本身占用了四个字节,也就是位于[ebp-44h]的位置。那么最后的va_end呢,也不复杂,也就是把[ebp-44h]的位置清零了一下。但是可虑到这里的va是一个临时变量,是否清零其实意义不大。那么,这里的ebp+0xc是什么意思呢?首先我们看到,ebp上面的数值是原来push ebp的数值,ebp+4是函数的返回地址,ebp+8是str的地址,那么很明显,ebp+0xc就是第二个参数的地址。所以,我们可以对这个打印函数稍微改造一下,
void XiaoxingPrintf(char* str, ...){char buffer[64];vsprintf(buffer, str, &str + 1);printf("%s\n", buffer);}同样一个函数,三句话就可以搞定了。不再需要记住那么多头文件和数据类型。当然,这背后需要你对函数堆栈、参数地址、ebp和esp理解得比较深刻和具体了。
- 随想录(由自定义打印函数想到的)
- 由《软件随想录》想到项目管理
- 由GetDlgItem函数想到的
- 由rand()函数想到的
- 由函数clock想到的
- 随想录(函数压栈)
- 由函数想到的生活哲学
- 由strcpy()函数想到的一些
- What:由函数Uri.parse()想到的
- 由C++绝对值函数想到的
- 《软件随想录》的随想
- 由《打印九九乘法表,要求只能用一个变量》想到的
- 随想录(招聘怎样的员工)
- 随想录(linux的四个维度)
- 随想录(linux的四个维度)
- 随想录(linux的四个维度)
- 随想录(程序员的缺点)
- 随想录(程序员的缺点)
- MATLAB中RGB图像的各分量灰度直方图
- HttpServlet的两个Service()方法区别
- 链表的三个经典问题
- 每日一练
- const修饰成员函数总结
- 随想录(由自定义打印函数想到的)
- SSH+ExtJs4开发项目的Demo实例视频讲解
- 编程珠玑笔记--排序
- oracle left join case when then
- Android利用Intent如何打开网页
- 算法之路
- hdu 1331 Function Run Fun(记忆化搜索)
- 《『若水新闻』客户端开发教程》——02.主界面设计
- Ruby on Rails,Routes配置routes.rb及请求解析规则