c – 使用printf-wide与多字节字符串文字打印UTF-8字符串

在这样的语句中,两者都输入具有相同编码(UTF-8)的源代码,并且正确设置了语言环境,它们之间有什么实际的区别吗?

printf("ο Δικαιοπολις εν αγρω εστιν\n");
printf("%ls", L"ο Δικαιοπολις εν αγρω εστιν\n");

因此,在输出时,是否有理由偏爱一个人呢?我想像第二次表现比较差一点,但它是否比多字节文字有任何优势(或劣势)?

编辑:这些字符串打印没有问题.但是我没有使用宽字符串函数,因为我也想使用printf等.所以问题是这些打印任何不同的方式(给定上述情况),如果是这样,第二个有什么优势?

编辑2:按照以下意见,我现在知道这个程序是有效的 – 我认为这是不可能的:

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进行输出.

最佳答案
printf("ο Δικαιοπολις εν αγρω εστιν\n");

打印字符串文字(const char *,特殊字符表示为多字节字符).虽然您可能会看到正确的输出,但在处理这些非ASCII字符时,还可能遇到其他问题.例如:

char str[] = "αγρω";
printf("%d %d\n", sizeof(str), strlen(str));

输出9 8,因为这些特殊字符中的每一个都用2个字符表示.

使用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控制台的情况下,通过调用_setmode,stdout的翻译模式应该显式设置为其中一种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;
}

转载注明原文:c – 使用printf-wide与多字节字符串文字打印UTF-8字符串 - 代码日志