2.1字符编码
Windows在Vista中,每个Unicode字符都使用UTF-16编码,UTF的全称是Unicode Transformation Format(Unicode 转换格式)。UTF-16将每个字符编码为2个字节(或者说16位)。
注意:.Net Framework 始终使用UTF-16来编码所有字符和字符串,所以在我们开发的Windows应用程序中,如果需要在本机代码(native code)和托管代码(managed code)之间传递字符和字符串,使用UTF-16能改进性能和减少内存消耗。
Unicode:是1988年由Apple和Xerox共同建立的一项标准。
UTF-8:一些字符编码为1个字节,一些字符编码为2个字节,一些字符编码为3个字节,一些字符编码为4个字节。
UTF-16:将每个字符编码为2个字节(或者说16位)。
UTF-32:将每个字符编码为4个字节(或者说32位)。
2.2 ANSI字符和Unicode字符与字符串数据类型
C语言中用char数据类型来表示一个8位ANSI字符。声明一个字符串时,C编译器会把字符串中的字符转换成8位char数据类型构成一个数组。
//An 8-bit character
char c = ‘A’;
//An array of 99 8-bit character and 8-bit terminating zero
char szBuffer[100] = “A String”;
Windows内建数据类型wchar_t,它表示一个16位的Unicode(UTF-16)字符。声明一个Unicode字符和字符串方法:
//An 16-bit character
wchar_t c = L’A’;
//An array of 99 8-bit character and 8-bit terminating zero
wchar_t szBuffer[100] = L”A String”;
字符串之前的大写字母L通知编译器该字符应当编译为一个Unicode字符串。当编译器将此字符串放入程序的数据段时,会使用UTF-16来编码每个字符,在每个ASCII字符间都用一个0来加以区分。
Windows 开发团队定义自己的数据类型,在Windows头文件WinNT.h中定义了一下数据类型:
type char CHAR; //An 8-bit character
type wchar_t WCHAR; //An 16-bit character
更多数据类型请查看WinNT.h头文件。
另外,在写代码的时候,可以使用ANSI或Unicode字符/字符串使其能够通过编译。WinNT.h定义了一下类型和宏:
#ifdef UNICODE
typedef WCHAR TCHAR, *PTCHAR, PTSTR;
typedef CONST WCHAR *PCTSTR;
#define _TEXT(qute) L##quote
#else
typedef CHAR TCHAR, *PTCHAR, PTSTR;
typedef CONST CHAR *PCTSTR;
#define _TEXT(qute) quote
#endif
#define TEXT(qute) _TEXT(qute)
这样无论使用ANSI还是Unicode字符,它都能通过编译。
2.3 Windows 中的Unicode函数和ANSI函数
如果一个Windows函数参数列表中有字符串,则该函数通常有两个版本。例如,一个CreateWindowsEx接受Unicode字符串,另一个CreateWindowsEx接受ANSI字符串。
在winUser.h中,CreateWindowEx实际是一个宏,定义如下:
#ifdef UNICODE
#define CreateWindowsEx CreateWindowsExW
#else
#define CreateWindowsEx CreateWindowsExA
#endif
在编译源码时,是否定义UNICODE决定着调用那一个版本CreateWindowsEx。在Windows 中,CreateWindowsExA的源码只是一个转换层,它负责分配内存,以便将ANSI字符串转换为Unicode字符串。然后 ,代码会调用CreateWindowsExW,并向它传递转换后的字符串。CreateWindowsExW返回时,CreateWindowsExA会释放它的内存缓冲区。由于系统需要执行这些转换操作,所以应用程序需要更多的内存,而且运行速度较慢。目前已知Windows的这些转换函数存在一些bug,所以尽可能开始就使用Unicode。
2.4 C 运行库中的Unicode和ANSI函数
同Windows函数一样,C运行库提供了一系列函数来处理ANSI字符和字符串,并提供了另一系列函数来处理Unicode字符和字符串。例如:
头文件TChar.h
#ifdef _UNICODE
#define _tcslen wcslen
#else
#define _tcslen strlen
#endif
现在明白应该在代码中调用_tcslen。
2.5 C 运行库中的安全字符串函数
任何修改字符串的函数都存在一个安全隐患:如果目标字符串缓冲区不够大,无法容纳所生成的字符串,就会导致内存中的数据被破坏。
2.5.1 初识新的安全字符串函数
2.5.2 在处理字符串时如何获得更多控制
2.5.3 Windows字符串函数
2.6 为何要用Unicode
Windows系统都采用Unicode,你有什么理由不使用Unicode编程。
2.7 推荐的字符和字符串的处理方式
2.8 Unicode和ANSI字符串转换
我们使用Windows函数 MultiByteToWideChar 将多字节字符串转换位宽字符字符串。
int MultiByteToWideChar(
UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr,
int cbMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar
);
对应地,WideCharToMultiByte 函数将款字符字符串转换为多字节字符串。
int WideCharToMultiByte(
UINT CodePage,
DWORD dwFlags,
LPCWSTR lpWideCharStr,
int cchWideChar,
LPSTR lpMultiByteStr,
int cbMultiByte,
LPCSTR lpDefaultChar,
LPBOOL lpUsedDefaultChar
);
2.8.1 导出ANSI和Unicode DLL 函数
2.8.2 判断文本是ANSI还是Unicode