编码 |
字节数 |
类型 |
字符(串)常量 |
WinNT.h中的定义 |
ANSI |
8bit |
char |
'A' "A string" |
typedef char CHAR; typedef CHAR *PCHAR; typedef CHAR *PSTR; typedef CONST CHAR *PCSTR; |
Unicode (UTF-16) |
16bit |
wchar_t 通过编译器设置/Zc:wchar_t支持 |
L'A' L"A string" |
typedef char CHAR; typedef CHAR *PWCHAR; typedef CHAR *PWSTR; typedef CONST CHAR *PCWSTR; |
WinNT.h头文件中定义字符类型宏,TCHAR、PTCHAR、PTSTR、PCTSTR、TEXT(),可在ANSI和Unicode编码间通用。
2. Windows函数中关于字符编码的信息
3. C运行时库中关于字符编码的信息
4. C运行时库的安全字符函数
潜在隐患:目标字符缓冲区未能承载结果字符,导致内存崩溃。
解决方法:包含StrSafe.h头文件
a. 使用_tcscpy_s、_tcscat_s代替_tcscpy、_tcscat,其函数原型为
errno_t _tcscpy_s(PTSTR strDestination, size_t numberofCharacters, PCSTR strSource);
errno_t _tcscat_s(PTSTR strDestination, size_t numberofCharacters, PCSTR strSource);
错误处理方法:
① 定义一错误处理函数,函数原型如下:
void InvalidParameterHandler(PCSTR expression, PCSTR function, PCSTR file, unsigned in line, uintptr_t /*pReserved*/);
② 使用_set_invalid_parameter_handler注册处理函数;
③ 程序开始时,调用_CrtSetReportMode(_CRT_ASSERT, 0)关闭断言对话框。
b. 更多对字符处理的控制
包括以字符数目计算缓冲区大小的函数,函数名中带有Cch(count of characters)
StringCchCat(Ex),StringCchCopy(Ex),StringCchPrintf(Ex)
和以字节数计算缓冲区大小的函数,函数名中带有Cb(count of bytes)
StringCbCat(Ex),StringCbCopy(Ex),StringCbPrintf(Ex)
S_OK:表示字符处理成功;
STRSAFE_E_INVALID_PARAMETER:非法参数,如pszDest为NULL、错误的dwFlags等;
STRSAFE_E_INSUFFICIENT_BUFFER
:目标字符串缓冲区空间不足,但目标字符串会尽可能放入字符并以'\0'结束字符串。
LPTSTR* ppszDestEnd:返回目的字符串缓冲区结束字符('\0')的字符指针;
size_t* pcchRemaining:返回目的字符串缓冲区未使用字符数;
DWORD dwFlags:关于字符处理的标记。
数值 |
描述 |
STRSAFE_FILL_BEHIND_NULL |
当函数运行成功时,将dwFlags低字节填充到目的字符串未初始化的字符上。 |
STRSAFE_IGNORE_NULLS |
将NULL字符串指针视为(TEXT(""))。 |
STRSAFE_FILL_ON_FAILURE |
当函数运行失败时,将dwFlags低字节填充到整个目的字符串上,除了第一个字符设置为'\0'。 |
STRSAFE_NULL_ON_FAILURE |
当函数运行失败时,将目的字符串的第一个字符设置为'\0',并将字符串视为(TEXT(""))。 |
STRSAFE_NO_TRUNCATION |
目的字符串被设置为(TEXT(""))。 |
c. Windows字符函数关于字符串比较的函数
可使用CompareString(Ex)和CompareStringOrdinal比较字符串:
宏 |
数值 |
描述 |
0 |
字符串比较操作失败。 |
|
CSTR_LESS_THAN |
1 |
pString1小于pString2。 |
CSTR_EQUAL |
2 |
字符串相等。 |
CSTR_GREATER_THAN |
3 |
pString1大于pString2。 |
5. 使用Unicode的理由
6. 使用字符及字符串的推荐方法
7. 操作字符串的推荐方法
对于缓冲区的操作,C运行时库提供了相应的更新版本,例如memcpy_s,memmove_s,wmemcpy_s,wmemmove_s。使用这些函数,需要声明__STDC_WANT_SECURE_LIB__宏和包含CrtDefs.h;
8. Unicode与ANSI的相互转化
int MultiByteToWideChar(UINT uCodePage, DWORD dwFlag, PCSTR pMultiByteStr, int cbMultiByte, PWSTR pWideCharStr, int cchWideChar)
转换步骤:
① 以NULL为pWideCharStr的值、0为cchWideChar的值、-1为cbMultiByte的值调用MultiByteToWideChar,由返回值得到源字符串的字符个数;
② 分配内存,大小为源字符串的字符个数×sizeof(wchar_t);
③ 再次调用MultiByteToWideChar,将目的字符串缓冲区地址、字符个数等参数传入;
④ 使用字符;
⑤ 释放字符。
int WideCharToMultiByte(UINT uCodePage, DWORD dwFlag, PCWSTR pWideCharStr, int cchWideChar, PSTR pMultiByteStr, int cbMultiByte, PCSTR pDefaultChar, PBOOL pfUsedDefaultChar)
转换步骤:
与MultiByteToWideChar类似。参数pDef
aultChar作为默认字符,用于替代未能在多字节字符中找到对应字符的宽字符,pfUsedDefaultChar用于返回是否有宽字符未能找到对应的多字节字符。
在CPP文件中:
void FuncW(PWSTR pWideCharStr, DWORD cchLength) { ...... } void FuncA(PSTR pMultiByteStr, DWORD cchLength) { PWSTR pWideCharStr; int nLenOfWideCharStr; nLenOfWideCharStr = MultiByteToWideChar(CP_ACP, 0, pMultiByteStr, cchLength, NULL, 0); pWideCharStr = (PWSTR) HeapAlloc(GetProcessHeap(), 0, nLenOfWideCharStr * sizeof(wchar_t)); If (pWideCharStr == NULL) return; MultiByteToWideChar(CP_ACP, 0, pMultiByteStr, cchLength, pWideCharStr, nLenOfWideCharStr); FuncW(pWideCharStr, cchLength); WideCharToMultiByte(CP_ACP, 0, pWideCharStr, cchLength, pMultiByteStr, (int)strlen(pMultiByteStr), NULL, NULL); HeapFree(GetProcessHeap(), 0, pWideCharStr); return; }
在头文件中:
void FuncW(PWSTR pWideCharStr, DWORD cchLength); void FuncA(PSTR pMultiByteStr, DWORD cchLength); #ifdef UNICODE #define Func FuncW #else #define Func FuncA #endif
使用AdvApi32.dll中,在WinBase.h中定义的IsTextUnicode函数去区分文件使用的是ANSI还是Unicode编码。该函数并未能精确得出文件的编码。其函数原型为:
BOOL IsTextUnicode(CONST PVOID pvBuffer, int cb, PINT pResult);