只要语言环境设置正确,使用宽字符函数在使用 UTF-8 的系统上处理 UTF-8 文件就不会有任何问题。他们将能够正确地解释事物,即他们会根据需要将一个字符视为 1-4 个字节(在输入和输出中)。您可以通过以下方式对其进行测试:
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
int main()
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
// setlocale(LC_CTYPE, ""); // to use environment variable instead
wchar_t *txt = L"£Δᗩ";
wprintf(L"The string %ls has %d characters\n", txt, wcslen(txt));
}
$ gcc -o loc loc.c && ./loc
The string £Δᗩ has 3 characters
如果你不小心在多字节字符串上使用标准函数(特别是字符函数),事情就会开始崩溃,例如:
char *txt = "£Δᗩ";
printf("The string %s has %zu characters\n", txt, strlen(txt));
$ gcc -o nloc nloc.c && ./nloc
The string £Δᗩ has 7 characters
该字符串在这里仍然可以正确打印,因为它本质上只是一个字节流,并且由于系统需要 UTF-8 序列,因此它们被完美地翻译了。当然strlen
是报告字符串中的字节数,7(加上\0
),但不理解字符和字节是不等价的。
在这方面,由于 ASCII 和 UTF-8 之间的兼容性,只要小心,您通常可以将 UTF-8 文件视为简单的多字节 C 字符串。
还有一定程度的灵活性。可以轻松地将标准 C 字符串(作为多字节字符串)转换为宽字符串:
char *stdtxt = "ASCII and UTF-8 €£¢";
wchar_t buf[100];
mbstowcs(buf, stdtxt, 20);
wprintf(L"%ls has %zu wide characters\n", buf, wcslen(buf));
Output:
ASCII and UTF-8 €£¢ has 19 wide characters
在流上使用宽字符功能后,它会设置为宽方向。如果以后要使用标准字节 i/o 函数,则需要先重新打开流。这可能就是为什么建议不要在stdout
. 但是,如果您只在stdin
and上使用宽字符函数stdout
(包括您链接到的任何代码),您将不会遇到任何问题。