- UID
- 1
- 精华
- 积分
- 76361
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
经常看到一个函数有两种原型,这里拿MessageBox举例,User32.dll并没有导出MessageBox这个符号,它导出的是MessageBoxA和MessageBoxW。这两者的区别是:
MessageBoxA以ANSI编码,MessageBoxW以Unicode编码。
MessageBoxA的原型:
- WINUSERAPI
- int
- WINAPI
- MessageBoxA(
- _In_opt_ HWND hWnd,
- _In_opt_ LPCSTR lpText,
- _In_opt_ LPCSTR lpCaption,
- _In_ UINT uType);
复制代码 而MessageBoxW的原型:- WINUSERAPI
- int
- WINAPI
- MessageBoxW(
- _In_opt_ HWND hWnd,
- _In_opt_ LPCWSTR lpText,
- _In_opt_ LPCWSTR lpCaption,
- _In_ UINT uType);
复制代码 这两者的参数,一个用的是LPCSTR,一个用的是LPCWSTR。
其中LPCSTR是多字节编码字符串指针(ANSI),而LPCWSTR则是宽字节编码字符串指针,也就是Unicode。使用Unicode的好处是字符的处理比ANSI快,效率高。而Unicode比较费内存(每个字符的字节数都一样),ANSI的话第0-127字符是单字节的。
当你的预编译器被你添加了UNICODE的定义,那么你调用MessageBox实际上调用的是MessageBoxW,TCHAR实际上是WCHAR(typedef unsigned short WCHAR;)
这里说一下为什么微软的很多代码都把指针定义为LPXXXXX,比如上述的LPCSTR、LPCWSTR等玩意儿,LP是什么意思?是long pointer(长指针)。
在以前16位DOS编程的年代,内存是分段管理的。所谓分段管理,首先16位数(比如0xFFFF)能表示的最大范围是0-65535,也就是64K的内存空间,然后CPU在实模式下能访问1MB的内存空间——这是怎么做到的呢?靠的是分段机制——段寄存器的值乘以16加上“偏移”(短指针),就是实际的内存地址了。然后你要跨段访问内存的话(假设你的DS只向0xA0000处,你要访问0x00000处的内存),你就得用远指针,然后就有了long pointer(far pointer)这种说法了。
结果从Windows 3.2开始到现在Win8.1,都没有摆脱LP这种前缀。模仿微软写LP的家伙们你们够了。 |
|