【问题标题】:Unicode vs Multi-byteUnicode 与多字节
【发布时间】:2011-01-14 15:41:41
【问题描述】:

我真的被这个 unicode 和多字节的东西弄糊涂了。

假设我正在用 Unicode 编译我的程序(但最终,我想要一个独立于所用字符集的解决方案)。

1) 所有的 'char' 都会被解释为宽字符吗?

2) 如果我有一个简单的 printf 语句,即 printf("Hello World\n");没有字符串,我可以不使用 _tprintf 和 _T("...") 吗?如果 printf 语句包含一个字符串,那么我应该使用 _tprintf 和 _T("..."),即 _tprintf("Hello %s\n", name); ?

3) 如果我有一个要读入缓冲区的文本文件(以默认格式保存,即不更改使用的默认字符集),我还可以使用 char 代替 TCHAR 吗?特别是如果我逐个字符地阅读它,即通过增加字符指针?

谢谢。

问候, 雷恩

【问题讨论】:

  • 补充一下,我使用的是 Visual Studio .NET 2003,而且我主要使用 C/C++ 进行编程。

标签: c unicode visual-c++ multibyte


【解决方案1】:

首先,如果您使用UNICODE/_UNICODE进行编译并且不打算针对其他平台,您可以避免使用TCHAR业务并使用WCHAR(或wchar_t)和W无处不在的功能。

1) 所有的 'char' 都会被解释为宽字符吗?

char 在 C 中是--根据定义--1 个字节。 (这在技术上并不排除它在wchar_t 也是 1 字节的平台上成为“宽字符”,但鉴于您使用的是 MSVC 并且针对 Windows 平台,情况并非如此。)

所以出于实际目的,这个问题的答案是:不。

2) 如果我有一个简单的 printf 语句,即 printf("Hello World\n");没有字符串,我可以不使用 _tprintf 和 _T("...") 吗?如果 printf 语句包含一个字符串,那么我应该使用 _tprintf 和 _T("..."),即 _tprintf("Hello %s\n", name); ?

如果您要打印 ASCII 字符串文字,您可以继续使用 printf

如果要打印可能超出 ASCII 范围的任意字符串,则应使用 _tprintf(或 wprintf)。

3) 如果我有一个要读入缓冲区的文本文件(以默认格式保存,即不更改使用的默认字符集),我还可以使用 char 代替 TCHAR 吗?特别是如果我逐个字符地阅读它,即通过增加字符指针?

什么是“默认格式”?

当您读取外部文件时,您应该首先读取前几个字节以检查 UTF-16 或 UTF-8 BOM,然后根据它做出决定。

【讨论】:

  • 关于 printf 问题:您可以通过应用“%ls”格式说明符对 wchar_t 字符串使用 printf。这不是您打印的内容,而是您希望从 printf 系列中获得哪种类型的输出来决定您使用哪种输出。
  • @jovaha:在当前编码中无法表示的wchar_t 字符串上使用printf%ls 不太有效。不过,您的观点是正确的,IMO 我们都是对的。
  • UTF-8 不需要 BOM;无论如何,MS 系统可能会把它放在那里。
【解决方案2】:

1) 所有的 'char' 都会被解释为宽字符吗?

没有。但是所有TCHARs 都会被解释为wchar_ts

考虑 winnt.h 可能如何指定:

#ifdef UNICODE
 typedef WCHAR TCHAR;
#else
 typedef CHAR TCHAR;
#endif

当您调用SomeApi() 时,它将换行到SomeApiA(char *arg)SomeApiW(wchar_t *arg)。 (参数实际上是 TCHAR 的,但你明白了)。

因此,您的源代码将是“独立的”,因为它可以编译成“ANSI”或 Widechar 版本。为此,您需要使用 TCHAR's 而不是原始类型。

2) 如果我有一个简单的 printf 语句,即 printf("Hello World\n");没有字符串,我可以不使用 _tprintf 和 _T("...") 吗?如果 printf 语句包含一个字符串,那么我应该使用 _tprintf 和 _T("..."),即 _tprintf("Hello %s\n", name); ?

我不知道tprintf 家族,但我可以推测它们的工作方式与上述定义相同。也就是说,tprintfTCHAR's 作为参数并依赖于UNICODE 设置将它们视为chars 或wchar_ts。

3) 如果我有一个要读入缓冲区的文本文件(以默认格式保存,即不更改使用的默认字符集),我还可以使用 char 代替 TCHAR 吗?特别是如果我逐个字符地阅读它,即通过增加字符指针?

文件的内容使用什么字符编码完全取决于它自己,与TCHAR的无关。 TCHAR's 用于文件名,以便您在 win32 API 调用中使用。

【讨论】:

    【解决方案3】:

    假设我正在用 Unicode 编译我的程序(但最终,我想要一个独立于所用字符集的解决方案)。

    这将取决于您的语言 - 例如编程语言而不是人类口语。 “用 Unicode 编译我的程序”是什么意思?

    1. 所有 'char' 都会被解释为宽字符吗?

      • 这取决于所选择的语言和选项。例如,Java 使用 16 位字符(存储 UTF-16 或 UCS-2——很久以前它是 UCS-2,但我认为它现在是 UTF-16)。在 C 语言中,您必须非常努力地将基本的 'char' 类型解释为 8 位以外的任何内容 - 至少在基于 Unix 的编译器上是这样。
    2. 如果我有一个简单的 printf 语句,即 printf("Hello World\n");没有字符串,我可以不使用 _tprintf 和 _T("...") 吗?如果 printf 语句包含一个字符串,那么我应该使用 _tprintf 和 _T("..."),即 _tprintf("Hello %s\n", name); ?

      • 这需要对您正在使用的平台有所了解,因为它远非标准。我怀疑这是 MSVC ......这让我更难成为权威,因为我不使用 MSVC。但是,ISO C99 标准(MSVC 明显不支持)提供了诸如fwprintf() 之类的函数来打印宽字符字符串。如果您需要有关特定编译器的信息,请用正确的信息标记您的问题。
    3. 如果我有一个想要读入缓冲区的文本文件(以默认格式保存,即不更改使用的默认字符集),我还可以使用 char 代替 TCHAR 吗?特别是如果我逐个字符地阅读它,即通过增加字符指针?

      • 同样,TCHAR 不是标准的 - 它高度特定于 MSVC。在标准 C 中,当您对其应用适当的函数时,文件流将获得“方向”(面向宽或面向字节)。在关闭(或使用 freopen() 重新打开)之前,它会保持该方向。

    【讨论】:

      猜你喜欢
      • 2017-05-30
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-21
      • 1970-01-01
      相关资源
      最近更新 更多