//----------------------------------------- //本程序展示了如何实现MessageBoxPrintf函数 //本函数能像printf那样格式化输出 //摘录自:《windows程序设计第五版》 //----------------------------------------- #include<windows.h> #include<tchar.h> #include<stdio.h> int CDECL MessageBoxPrintf(TCHAR * szCaption, TCHAR * szFormat, ...) { TCHAR szBuffer[1024]; va_list pArgList; va_start (pArgList, szFormat); _vsntprintf_s(szBuffer,sizeof(szBuffer)/sizeof(TCHAR), sizeof(szBuffer) / sizeof(TCHAR),szFormat, pArgList); //--------------------------------------------------------------------------------------------------------------------------------- //原文使用_vsntprintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR),szFormat, pArgList); vs认为此函数具有安全性问题 因此我替换成上边的函数 //--------------------------------------------------------------------------------------------------------------------------------- va_end(pArgList); return MessageBox(NULL,szBuffer,szCaption,0); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { int cxScreen; int cyScreen; cxScreen = GetSystemMetrics(SM_CXSCREEN); cyScreen = GetSystemMetrics(SM_CYSCREEN); MessageBoxPrintf(TEXT("SCREEN SIZE"),TEXT("您的视屏显示器:\nWIDE:%i\nHIGH: %i"),cxScreen,cyScreen); return 0; }
这个函数使用了可变参数 这样就出现了一些陌生的东西,解释如下
CDECL
__cdecl __fastcall与__stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数弹出栈,3)以及产生函数修饰名的方法。
1、__stdcall调用约定:函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈。
2、_cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。注意:对于可变参数的成员函数,始终使用__cdecl的转换方式。
3、__fastcall调用约定:它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈)。
va_start va_end等
函数名称,读取可变参数的过程其实就是在堆栈中,使用指针,遍历堆栈段中的参数列表,从低地址到高地址一个一个地把参数内容读出来的过程
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址
#define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效
在学习windows程序设计时此函数可以给c/c++程序员一份熟悉感。。。。。。。。。。。
时间: 2024-11-05 23:01:13