Windows 字符集

编程

Windows 字符集

刚开始使用 vc++ ,对于习惯了使用 gcc 的同志来说,其中的字符串是个很恼火的东西,原因是,在学习 c/c++ 中,使用的所有的字符都是 assic 码,在 Windows Api 编程时,各种字符串参数类型不匹配的报错,很是烦恼,有的代码,在手动操作控制台编译时,成功编译,在 visuall studio 中编译报错,各种字符串之间转换让人一头雾水。而查阅各种资料都很零散,故零散记录下来,待日后通透之时整理。

类型

字符类型

主要是两种类型,一种是 ANSI 一种是 Unicode,分别表示为 CHAR 、WCHAR \ wchar_t

前者占一个字节,后者占用两个字节

字符串类型

Windows 中的字符串类型真是……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 8位字符指针

typedef CHAR* PCHAR;

typedef CHAR* PSTR;

typedef CONSTCHAR* PCSTR

// 16位字符指针

typedef WCHAR* PWCHAR;

typedef WCHAR* PWSTR;

typedef CONSTWCHAR* PCWSTR;

当然还有 c++ 中的标准类型 String 和 MFC 中提供的 CString

按照不同的style字符类型分有五类:

C-Style ANSI类型字符串:CHAR *,PSTR, LPSTR, LPCSTR, PCHAR.

C-StyleUnicode类型字符串:WCHAR *, PWSTR, LPWSTR, PWCHAR,LPCWSTR.

C-Style 同时兼容ANSI和Unicode类型字符串:TEXT,__TEXT(), TCHAR *, PTSTR, LPTSTR, PCTSTR, LPCTSTR.

C-style和Pascal-Style兼并的字符串:BSTR

以上同种类型的字符串可以直接转换

例如:CHAR == PSTR == LPSTR 至于 LPCSTR 可使用强制类型转换


字符集

计算机上字符集可归为三种

  • 1.单字节字符集(SBCS)

​ 具体实现为 ASCII 和 扩展 ASCII,使用一个字节表示字符

  • 2.多字节字符集(MBCS)

​ 主要指在计算机推广后出现的一些地方字符集,例如中国的 GBK、GB18030、BIG5

​ 操作系统通过代码页(CodePage) 为哥哥字符集确定一个编号,例如:437(美国英语)、936(简体中文)、950(繁体中文)、949(朝鲜语—朝鲜)

  • 3.宽字节字符集(Unicode)

​ 标准化组织 ISO 提出的可以容纳世界上所有文字符号的编码方案

C运行时支持

c/c++ 为了支持新的 Unicode 字符集,定义了新的字符类型 wchat_t ,定义为 typedef usigned short wchar_t;

为了统一处理 窄字符(char)和宽字符类型(wchar_t),系统头文件 tchar.h 提供了一个数据类型 TCHAR,定义为:

1
2
3
4
5
#ifndef _UNICODE 
#define wchar_t TCHAR
#else
typedef char TCHAR;
#endif

所以,你可以写这样的代码

1
TCHAR ch = "sdfghjk"; // 如果定义了 UNICODE,则是宽字节,否则是窄字节

同样的,字符串处理的函数也提供了宽字节支持,例如字符串长度 strlen 有 wcslen 替代

而且,tchar.h 中也提供了对应的统一处理宏定义 _tcslen

1
2
3
4
5
#ifndef _UNICODE 
#define _tcslen wcslen
#else
#define c_tcslen strlen
#endif

ONE MORE THING

_T , _TEXT, _UNICODE, L 宏提供了相同的功能,表明后面的字符串是一串 宽字节 字符


C++标准库支持

c++ 中的 string 对应的宽字节版本为 wstring ,但是,没有提供统一处理函数定义

类似的类型还有 fstream/wstream、ofstream/wostream 等


Windows Api 支持

Windows 的 api 提供两个版本,例如 MessageBox 有两个实现版本 MesssageBoxA 和 MessageBoxW

你可以值调用 MessageBox ,让系统自己决定使用 宽字节还是窄字节版本。

Notice:自 Windows 2000 开始,Windows 内部核心函数都是用 Unicode 字符串,如果调用时传递给函数一个 ASCII 的字符串,Windows 会先将字符串转换为 Unicode 字符串。

字符集使用

Unicode 下 wstring 转 string

利用 API 函数 WideCharToMultiByte 转换

该函数声明如下, 具体信息参考资料 MSDN WideCharToMultiByte

1
2
3
4
5
6
7
8
9
10
int WideCharToMultiByte(
[in] UINT CodePage,
[in] DWORD dwFlags,
[in] _In_NLS_string_(cchWideChar)LPCWCH lpWideCharStr,
[in] int cchWideChar,
[out, optional] LPSTR lpMultiByteStr,
[in] int cbMultiByte,
[in, optional] LPCCH lpDefaultChar,
[out, optional] LPBOOL lpUsedDefaultChar
);

使用 A2W 和 W2A 宏 使PSTR 转 PWSTR

W2A 和 A2W,W2A代表将PWSTR转换为PSTR,反之A2W表示将PSTR转换为PWSTR

1
2
3
4
5
USES_CONVERSION;
PWSTR wszText = L"1.Unicode字符转换为ANSI;";
PSTR szText="2.ANSI字符转换成Unicode.";
printf("%s\n",W2A(wszText));
wprintf(L"%s\n",A2W(szText));

Author: 哒琳

Permalink: http://blog.jieis.cn/2022/f2bf9fe5-fac8-4c9b-8a04-4cdb9d19592e.html

Comments