c - 关于 Winapi 路径和文件名的说明(W 函数和 A 函数)



我尝试检查使用 W winapi 与 A 的重要性和原因,(W 表示宽字符,A 表示 ascii 对吗?

我做了一个简单的例子,我收到当前用户的临时路径,如下所示:

CHAR pszUserTempPathA[MAX_PATH] = { 0 };
WCHAR pwszUserTempPathW[MAX_PATH] = { 0 };
GetTempPathA(MAX_PATH - 1, pszUserTempPathA);
GetTempPathW(MAX_PATH - 1, pwszUserTempPathW);
printf("pathA=%srnpathW=%wsrn",pszUserTempPathA,pwszUserTempPathW);

我当前的用户有一个俄语名称,所以它是用西里尔文写的,printf 输出如下:

pathA=C:usersПыщьLocalTemp
pathW=C:usersПыщьLocalTemp

所以两条路径都没问题,我想我会收到一些错误,或者一堆带有GetTempPathA符号,因为当前用户是 unicode,但我发现,西里尔字符实际上包含在扩展的 ASCII 字符集中。所以我有一个问题,如果我使用我的软件,它会在当前用户的临时文件夹中提取数据,该用户是中国人(假设他的用户名中有中文符号),我会在使用GetTempPathA版本时遇到混乱或错误吗?对于直接使用 winapi 的生产软件,我是否应该始终使用W前缀函数?

首先,-A 后缀代表 ANSI,而不是 ASCII。 ASCII 是一个 7 位字符集。 ANSI,正如Microsoft使用术语的那样,用于使用 8 位代码单元 (chars) 和代码页的编码。

有些人使用术语"扩展ASCII"或"高ASCII",但这实际上不是一个标准,在某些情况下,与ANSI并不完全相同。 扩展 ASCII 是 ASCII 字符集加上(最多)128 个附加字符。 对于许多 ANSI 代码页,这与扩展 ASCII 相同,但某些代码页包含可变长度字符(Microsoft称为多字节)。 有些人认为"扩展ASCII"仅表示ISO-Latin-1(几乎与Windows-1252相同)。


无论如何,使用 ANSI 函数,字符串可以包含当前代码页中的任何字符。如果您需要不属于当前代码页的字符,那么您就不走运了。 您必须使用宽 -W 版本。

在现代版本的 Windows 中,通常可以将 -A 函数视为 -W 函数的包装器,这些函数使用 MultiByteToWideChar 和/或 WideCharToMultiByte 来转换通过 API 传递的任何字符串。 但后一种转换可能是有损的,因为宽字符串可能包含多字节字符串无法表示的字符。


可移植的跨平台代码通常以 UTF-8 格式存储所有文本,UTF-8 使用 8 位代码单元 (chars),但可以表示任何 Unicode 代码点,并且每当文本需要通过 Windows API 时,您都可以显式转换为宽字符/从宽字符转换,然后调用 API 的 -W 版本。

UTF-8 几乎类似于 Microsoft 所谓的多字节 ANSI 代码页,只是 Windows 不完全支持 UTF-8 代码页。 有CP_UTF8,但它仅适用于某些API(如WideCharToMultiByte和MultiByteToWideChar)。 不能将代码页设置为CP_UTF8并期望常规 -A API 执行正确的操作。


当您尝试测试内容时,请注意,很难(有时甚至不可能)让 CMD 控制台窗口在当前代码页之外显示字符。 如果要显示多脚本字符串,则可能应该编写 GUI 应用程序和/或使用调试器来检查字符串的实际内容。

当然,您需要宽版本。ASCII 版本在技术上甚至不能处理超过 256 个不同的字符。西里尔字母包含在扩展的 ASCII 集中(如果这是您的本地化),而中文不是也不能,因为需要更大的字符集来表示它。此外,你也可能弄乱西里尔文 - 只有当执行机器具有匹配的本地化时,它才能正常工作。因此,在具有非西里尔语本地化的机器上,文本将根据本地化设置定义的内容显示。

最新更新