在这样的语句中,两者都使用相同的编码(UTF-8)输入到源代码中并且语言环境设置正确,它们之间是否存在实际差异?
printf("ο Δικαιοπολις εν αγρω εστιν\n");
printf("%ls", L"ο Δικαιοπολις εν αγρω εστιν\n");
因此有什么理由在做输出时更喜欢一个而不是另一个?我想第二个表现得差一点,但它对多字节文字有任何优势(或劣势)吗?
编辑:这些字符串打印没有问题。但是我没有使用宽字符串函数,因为我希望能够使用printf
等。所以问题是这些打印方式是否有所不同(鉴于上述情况),如果是这样,第二种方式是否有任何优势?
EDIT2:根据以下评论,我现在知道这个程序有效 - 我认为这是不可能的:
int main()
{
setlocale(LC_ALL, "");
wprintf(L"ο Δικαιοπολις εν αγρω εστιν\n"); // wide output
freopen(NULL, "w", stdout); // lets me switch
printf("ο Δικαιοπολις εν αγρω εστιν\n"); // byte output
}
EDIT3 :我已经做了一些进一步的研究,看看这两种类型正在发生什么。拿一个更简单的字符串:
wchar_t *wides = L"£100 π";
char *mbs = "£100 π";
编译器生成不同的代码。宽字符串是:
.string "\243"
.string ""
.string ""
.string "1"
.string ""
.string ""
.string "0"
.string ""
.string ""
.string "0"
.string ""
.string ""
.string " "
.string ""
.string ""
.string "\300\003"
.string ""
.string ""
.string ""
.string ""
.string ""
第二个是:
.string "\302\243100 \317\200"
在查看Unicode编码时,第二种是纯UTF-8。宽字符表示是UTF-32。我意识到这将取决于实现。
那么文字的宽字符表示可能更便携?我的系统不会直接打印UTF-16 / UTF-32编码,因此它会自动转换为UTF-8进行输出。
答案 0 :(得分:25)
printf("ο Δικαιοπολις εν αγρω εστιν\n");
打印字符串文字(const char*
,特殊字符表示为多字节字符)。虽然您可能会看到正确的输出,但在处理非ASCII字符时可能会遇到其他问题。例如:
char str[] = "αγρω";
printf("%d %d\n", sizeof(str), strlen(str));
输出9 8
,因为每个特殊字符都由2 char
s表示。
使用L
前缀时,您的文字由宽字符(const wchar_t*
)和%ls
格式说明符组成,导致这些宽字符转换为多字节字符(UTF-8)。请注意,在这种情况下,应该适当地设置区域设置,否则此转换可能导致输出无效:
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main(void)
{
setlocale(LC_ALL, "");
printf("%ls", L"ο Δικαιοπολις εν αγρω εστιν");
return 0;
}
但是在使用宽字符时,有些事情可能会变得更复杂,但其他事情可能会变得更简单,更直接。例如:
wchar_t str[] = L"αγρω";
printf("%d %d", sizeof(str) / sizeof(wchar_t), wcslen(str));
将按照人们自然期望输出5 4
。
一旦您决定使用宽字符串,wprintf
可用于直接打印宽字符。这里还值得注意的是,在Windows控制台的情况下,stdout
的翻译模式应该通过调用_setmode
显式设置为其中一种Unicode模式:
#include <stdio.h>
#include <wchar.h>
#include <io.h>
#include <fcntl.h>
#ifndef _O_U16TEXT
#define _O_U16TEXT 0x20000
#endif
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
wprintf(L"%s\n", L"ο Δικαιοπολις εν αγρω εστιν");
return 0;
}