0xAA55 发表于 2014-8-23 09:40:32

【常识贴】Windows编程时遇到的A和W、P和LP是什么意思

经常看到一个函数有两种原型,这里拿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的家伙们你们够了。
页: [1]
查看完整版本: 【常识贴】Windows编程时遇到的A和W、P和LP是什么意思