Linux 上的 wprintf UTF16(应该是 UTF8)?

Posted

技术标签:

【中文标题】Linux 上的 wprintf UTF16(应该是 UTF8)?【英文标题】:wprintf UTF16 (should be UTF8) on Linux? 【发布时间】:2011-12-03 18:44:56 【问题描述】:

1 wprintf 显示 'Ω' 为 3A9 (UTF16) 真的很奇怪,但是 wctomb convert wchar 到 CEA9 (UTF8),我的语言环境是默认 en_US.utf8。正如手册页所说, 它们应该符合我的语言环境,但 wpritnf 使用 UTF16,为什么?

摘自http://www.fileformat.info/info/unicode/char/3a9/index.htm

UTF 中的Ω

UTF-8(十六进制)0xCE 0xA9(cea9)

UTF-16(十六进制)0x03A9 (03a9)

2 wprintf 和 printf 不能在同一个程序中运行,我有 选择使用 wprintf 或 printf,为什么?


查看我的程序:

#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <locale.h>

int main() 
  setlocale(LC_ALL,""); // inherit locale setting from environment
  int r;
  char wc_char[4] = 0,0,0,0;
  wchar_t myChar1 = L'Ω'; //greek 

  // should comment out either wprintf or printf, they don't run together
  r = wprintf(L"char is %lc (%x)\n", myChar1, myChar1);//On Linux, to UTF16

  r = wctomb(wc_char, myChar1); // On Linux, to UTF8
  r = printf("r:%d, %x, %x, %x, %x\n", r, wc_char[0], wc_char[1], wc_char[2], wc_char[3]);

【问题讨论】:

我不确定你在问什么,但我可以告诉你 UTF-16 从未在 Linux 上的 charwchar_t 中使用。 (而且它不能用于任何符合 C 的实现。) 如果你运行程序,wprintf ("%x", myChar1);打印 3a9(UTF16 中的Ω)但不打印 cea9(UTF8 中的Ω) 据我所知wchar_t 在 Linux 中是 32 位的。正如 R.. 所说,它不是 UTF-16。我认为语言环境只影响非宽字符功能。 (如果我错了,请纠正我) @Mysticial:反过来。非宽函数是纯字节复制,除了%ls%lcprintfscanf。宽函数将它们输出的所有宽字符转换为语言环境的编码。 @R..:谢谢,很高兴知道。 (我显然不会经常更改我的语言环境...XD) 【参考方案1】:

第二个问题的答案与stream orientation 有关。您不能混合使用 printf()wprintf(),因为它们需要不同的方向。

当流程开始时,流尚未设置。在第一次调用使用流的函数时,它会被相应地设置。 printf() 将方向设置为正常,wprintf() 将其设置为宽。

调用需要与当前设置不同的方向的函数是未定义的行为。

【讨论】:

OP 有一个评论,应该评论其中一个或另一个。我认为这不是问题,但问题的措辞并不明确...... @R..:我也注意到了这一点,尽管 OP 询问为什么会这样。但无论如何,我同意,这个问题有点不清楚——我不得不读了好几遍才能理解它的要点。 抱歉,我的母语不是英语。 @user5652:不用担心。我们不会反对你。【参考方案2】:

您如何确定wprintf 行正在打印什么?您在问题下方的评论似乎暗示您只是在检查wprintf ("%x", myChar1); 的结果,无论字符编码如何,它都会打印myChar1 的内部数值(但不考虑字符集——存在差异);假设您的编译器在内部使用 Unicode 表示 wchar_ts(我相信这是一个非常安全的选择),这只是打印出 'Ω' 的 Unicode 代码点,即 0x3a9,独立于 UTF-16 与 UTF-8 的区别。为了判断 wprintf 是否打印 UTF-16,您必须直接检查输出的原始字节(例如,hexdump(1))。例如,在我的计算机上,wprintf 行打印以下内容:

63 68 61 72 20 69 73 20 ce a9 20 28 33 61 39 29 0a
c  h  a  r     i  s     Ω        (  3  a  9  )  \n

请注意,欧米茄在 UTF-8 中编码为字节 CE A9,但 wchar_t 的数值仍然是 3A9。

【讨论】:

是否涉及某种环境变量?当我在我的 ubuntu 系统上尝试它时,输出是 'char is ? (3a9)'。看起来 wprintf 将 omega 转换为问号,因为它不知道我在一个可以显示 utf-8 的终端上。我什至将 LC_CTYPE 设置为 en_US.UTF-8 并没有帮助。【参考方案3】:

啊,我可能已经找到了。你需要执行

setlocale(LC_ALL, "")

首先。看起来 wchar I/O 函数不支持 LC_ 环境变量。

有关更多背景信息,请参阅http://littletux.homelinux.org/knowhow.php?article=charsets/ar01s08。

【讨论】:

以上是关于Linux 上的 wprintf UTF16(应该是 UTF8)?的主要内容,如果未能解决你的问题,请参考以下文章

宽字符字符串字面量

在 Windows 和 Linux 下,在 C 中将 UTF-16 转换为 UTF-8

wprintf: %p 带 NULL 指针

将 UTF-16(Windows 上的 wchar_t)转换为 UTF32

尝试将简单的 UTF16 字符嵌入手动创建的 PDF 但失败

为啥在使用 wprintf 时 ©(版权符号)被替换为 (C)?