Windows 环境下的字符编码

在 Windows 环境中有两种常见的字符编码, 分别是 ASCII 和 Unicode

ASCII

在学习 C/C++ 中我们使用的字符以及字符串基本上都为 ASCII 编码 (即 char, char*, const char*. C++ STL中的 string 也不过是对 char 进行了封装), ASCII 编码的特点就是每个字符都只占一个字节, 表示范围为 0~127, 即 (00000000~01111111). 在后来又出现了扩展 ASCII 编码, 表示范围为 0~256, 即 (00000000~11111111)

Windows 编程中, 表示 ASCII 编码字符的数据类型为 :

CHAR, PCHAR, PSTR, LPSTR, LPCSTR

CHAR : 实际为 char

PCHAR : 实际为 char*

LPSTR : 实际为 char*

LPCSTR : 实际为 const char*

Unicode

Unicode 的出现是为了解决世界上非英语国家的字符表示问题, 例如中国, 日本, 韩国, 阿拉伯国家, 俄罗斯等等. 这些国家的字符容量远大于 ASCII 编码所能表示的字符容量. Unicode 编码的字符通常由两个字节来表示

Windows 编程中, 表示 Unicode 编码字符的数据类型为 :

WCHAR, PWCHAR, PWSTR, LPWSTR, LPCWSTR

WCHAR : 实际为 wchar_t (该数据类型属于 C/C++ 标准数据类型)

PWCHAR : 实际为 wchar_t*

LPWSTR : 实际为 wchar_t*

LPCWSTR : 实际为 const wchar_t*

关于这些数据类型中的 LP 其实指的是 long pointer, 即长指针. 在早期的 C 语言中分为长指针短指针, 主要区别在于表示的范围不同. 长指针能表示 32 位的地址, 而短指针则表示 16 位的地址. 不过随着操作系统和计算机硬件的不断完善和迭代, 目前已没有长指针与短指针之分

ASCII 与 Unicode 之间的转换

在 C/C++ 中, ASCII 与 Unicode 之间的转换并没有像之前学过的整型与浮点型之间的转换那样简单.

下面通过几种方式来进行 ASCII 与 Unicode 之间的转换

ASCII -> Unicode

可直接在 ASCII 编码的字符串之前加上 L

#include <windows.h>

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevinstance, LPSTR lpcmdline, int ncmdshow)
{
    LPCWSTR Text = L"你好, 世界!";
    LPCWSTR Title = L"标题栏";

    MessageBoxW(NULL, Text, Title, MB_OK);

    return 0;
}

可使用 API 函数 MultiByteToWideChar() 进行转换

#include <windows.h>

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevinstance, LPSTR lpcmdline, int ncmdshow)
{
    CHAR AscStr[256] = "你好, 世界!";
    WCHAR UnicStr[256];
    WCHAR Title[256] = L"标题栏";

    MultiByteToWideChar(CP_ACP, NULL, AscStr, -1, UnicStr, 256);	// ASCII -> Unicode

    MessageBoxW(NULL, UnicStr, Title, MB_OK);

    return 0;
}


关于 MultiByteToWideChar()

MSDN官方文档解释

Maps a character string to a UTF-16 (wide character) string. The character string is not necessarily from a multibyte character set.

大意 : 将多字节字符串 (其中包含 ASCII 编码的字符串) 转换为宽字节字符串 (其中包含 Unicode 编码的字符串).

MultiByteToWideChar() 的 API 结构

int MultiByteToWideChar(
  UINT                              CodePage,
  DWORD                             dwFlags,
  _In_NLS_string_(cbMultiByte)LPCCH lpMultiByteStr,
  int                               cbMultiByte,
  LPWSTR                            lpWideCharStr,
  int                               cchWideChar
);

参数解释

UINT                              CodePage

MSDN官方文档解释

Code page to use in performing the conversion. This parameter can be set to the value of any code page that is installed or available in the operating system. For a list of code pages, see Code Page Identifiers. Your application can also specify one of the values shown in the following table.

大意 : 该参数用来设置正在准备转换的字符串的代码表, 常用的有以下两种

CP_ACP : 即 ASCII 编码, 实现 ASCII 与 Unicode 之间的转换

CP_UTF8 : 即 UTF-8 编码, 实现 UTF-8 与 Unicode 之间的转换

DWORD                             dwFlags

MSDN官方文档解释

Flags indicating the conversion type. The application can specify a combination of the following values, with MB_PRECOMPOSED being the default. MB_PRECOMPOSED and MB_COMPOSITE are mutually exclusive. MB_USEGLYPHCHARS and MB_ERR_INVALID_CHARS can be set regardless of the state of the other flags.

大意 : 该参数为作为转换类型的标志. 一般设为 NULL

_In_NLS_string_(cbMultiByte)LPCCH lpMultiByteStr

MSDN官方文档解释

Pointer to the character string to convert.

大意 : 需要转换的多字节编码字符串的首地址

int                               cbMultiByte

MSDN官方文档解释

Size, in bytes, of the string indicated by the lpMultiByteStr parameter. Alternatively, this parameter can be set to -1 if the string is null-terminated. Note that, if cbMultiByte is 0, the function fails.

If this parameter is -1, the function processes the entire input string, including the terminating null character. Therefore, the resulting Unicode string has a terminating null character, and the length returned by the function includes this character.

If this parameter is set to a positive integer, the function processes exactly the specified number of bytes. If the provided size does not include a terminating null character, the resulting Unicode string is not null-terminated, and the returned length does not include this character.

大意 : 需要转换的多字节编码字符串的字节数, 可自行设置. 如果设置为 -1, 则长度为整个多字节编码字符串的长度 (包括 '\0' )

LPWSTR                            lpWideCharStr

MSDN官方文档解释

Pointer to a buffer that receives the converted string.

大意 : 接受已转换后的宽字节编码字符串的容器地址

int                               cchWideChar

MSDN官方文档解释

Size, in characters, of the buffer indicated by lpWideCharStr. If this value is 0, the function returns the required buffer size, in characters, including any terminating null character, and makes no use of the lpWideCharStr buffer.

大意 : 接受已转换后的宽字节编码字符串的容器大小, 可以自行设定. 如果是 0, 则函数返回字符串的长度


Unicode -> ASCII

可使用 API 函数 WideCharToMultiByte()

#include <windows.h>int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevinstance, LPSTR lpcmdline, int ncmdshow){    CHAR AscStr[256] = "你好, 世界!";    WCHAR UnicStr[256];    WCHAR TitleW[256] = L"标题栏";    CHAR TitleA[256];	    // ASCII -> Unicode    MultiByteToWideChar(CP_ACP, NULL, AscStr, -1, UnicStr, 256);	    MessageBoxW(NULL, UnicStr, TitleW, MB_OK);    /* Unicode -> ASCII */    WideCharToMultiByte(CP_ACP, NULL, UnicStr, -1, AscStr, 256, NULL, FALSE);    WideCharToMultiByte(CP_ACP, NULL, TitleW, -1, TitleA, 256, NULL, FALSE);    MessageBoxA(NULL, AscStr, TitleA, MB_OK);    return 0;}


关于 WideCharToMultiByte()

MSDN官方文档解释

Maps a UTF-16 (wide character) string to a new character string. The new character string is not necessarily from a multibyte character set.

大意 : 将宽字节字符串转换为多字节字符串

WideCharToMultiByte() 的 API 结构

int WideCharToMultiByte(  UINT                               CodePage,  DWORD                              dwFlags,  _In_NLS_string_(cchWideChar)LPCWCH lpWideCharStr,  int                                cchWideChar,  LPSTR                              lpMultiByteStr,  int                                cbMultiByte,  LPCCH                              lpDefaultChar,  LPBOOL                             lpUsedDefaultChar);

参数解释

_In_NLS_string_(cchWideChar)LPCWCH lpWideCharStr

MSDN 文档解释

Pointer to the Unicode string to convert.

大意 : 指向需要转换的宽字节编码字符串的首地址

int                                cchWideChar

MSDN 文档解释

Size, in characters, of the string indicated by lpWideCharStr. Alternatively, this parameter can be set to -1 if the string is null-terminated. If cchWideChar is set to 0, the function fails.

If this parameter is -1, the function processes the entire input string, including the terminating null character. Therefore, the resulting character string has a terminating null character, and the length returned by the function includes this character.

If this parameter is set to a positive integer, the function processes exactly the specified number of characters. If the provided size does not include a terminating null character, the resulting character string is not null-terminated, and the returned length does not include this character.

大意 : 需要转换的宽字节编码字符串的长度, 可自行设置. 如果设置成 -1, 则长度为整个宽字节编码字符串的长度 (包括 '\0' ).

LPSTR                              lpMultiByteStr

MSDN 文档解释

Pointer to a buffer that receives the converted string.

大意 : 指向存储转换后的多字节编码字符串的容器地址

int                                cbMultiByte

MSDN 文档解释

Size, in bytes, of the buffer indicated by lpMultiByteStr. If this parameter is set to 0, the function returns the required buffer size for lpMultiByteStr and makes no use of the output parameter itself.

大意 : 存储转换后的多字节编码字符串的容器大小, 可自行设置. 如果是 0, 则返回字符串的长度

LPCCH                              lpDefaultChar

MSDN 文档解释

Pointer to the character to use if a character cannot be represented in the specified code page. The application sets this parameter to NULL if the function is to use a system default value. To obtain the system default character, the application can call the GetCPInfo or GetCPInfoEx function.

For the CP_UTF7 and CP_UTF8 settings for CodePage, this parameter must be set to NULL. Otherwise, the function fails with ERROR_INVALID_PARAMETER.

大意 : 如果字符无法使用特定的 Code Page 来显示, 则使用该参数进行调整. 如果设置为 NULL 则使用系统默认的字符编码. 如果是 UTF-7 和 UTF-8 的转换也要设置为 NULL

LPBOOL                             lpUsedDefaultChar

MSDN 文档说明

Pointer to a flag that indicates if the function has used a default character in the conversion. The flag is set to TRUE if one or more characters in the source string cannot be represented in the specified code page. Otherwise, the flag is set to FALSE. This parameter can be set to NULL.

For the CP_UTF7 and CP_UTF8 settings for CodePage, this parameter must be set to NULL. Otherwise, the function fails with ERROR_INVALID_PARAMETER.

大意 : 用来反映是否使用了系统默认的字符编码. 设置为 TRUE 则表示为源字符串无法使用特定的 Code Page 来显示. 字符串在转换过程中如果都能使用特定的 Code Page 来显示, 则设置为 FALSE 或者 NULL.

对于 UTF-7 和 UTF-8 的转换则该参数必须设置为 NULL

上一篇:写Python爬虫遇到的一些坑 转载:https://mp.weixin.qq.com/s/kfxJ7EKFeunGcjvBr0l7ww


下一篇:xss-labs第八关