【问题标题】:C/C++ Unicode characters encoding sizes and default formatsC/C++ Unicode 字符编码大小和默认格式
【发布时间】:2014-02-15 13:25:31
【问题描述】:

我刚刚意识到(感谢我的大学课程)我认为我知道的关于 unicode 的许多事情都是错误的。因此,我开始阅读和修正我的知识,通过在 MSVC2012 中玩一个简单的“Hello world”C++ 程序,立即产生了以下疑问:

#include <iostream>
#include <string.h>
using namespace std;

int main(void) {

    char arr1[] = "I am a nice boy"; // Is this stored as UTF-8 (multi-byte) or ASCII?
    char arr[] = "I'm a nice èboi"; // All characters should be ASCII except the 'è' one, which encoding is used for this?
    cout << strlen(arr); // Returns 15 as ASCII, why?

    // If I choose "multi-byte character set" in my VS project configuration instead of "unicode", what does this mean and what
    // will this affect?

    char arr2[] = "I'm a niße boy"; // And what encoding is it used here?
    cout << strlen(arr2); // Returns 1514, what does this mean?

    // If UTF-32 usually use 4 bytes to encode a character (even if they're not needed), how can a unicode code point like U+FFFF
    // (FFFF hexadecimal is 65535 in decimal) represent any possible unicode character if the maximum is FFFF ? (http://inamidst.com/stuff/unidata/)

    return 0;
}

上面是用“多字节字符集”编译的,但由于多字节是一种 unicode 编码,我猜(?)即使这也不清楚。

有人可以为上述问题提供清晰的解释吗?

【问题讨论】:

  • 这不是关于 Unicode,而是关于 VS2012。如果您根本不了解您是否使用 Unicode,那么根本就没有 Unicode 问题。
  • 然后编辑问题并添加标签,如果您认为是这样。
  • 先生。克宁,我觉得你的语气不礼貌。您可以提出一个可以回答的问题。如果您知道您的源文件是 UTF-8 还是某些非 unicode 代码页,请编辑您的问题。如果您不这样做,请继续编辑您的问题,或者更好的是,找出然后编辑您的问题。
  • 我一开始就觉得你的语气不礼貌。请让我们都安顿下来。对不起,如果我写错了,那是因为我很困惑,而不是因为我试图表达自己的观点。我用 vs2012 标签和我设置的属性编辑了问题
  • 我认为你的代码会为第 8 行产生错误 " cout

标签: c++ visual-studio-2012 unicode character-encoding multibyte


【解决方案1】:
    char arr1[] = "I am a nice boy"; // Is this stored as UTF-8 (multi-byte) or ASCII?

这存储在编译器的执行字符集中。编译器可以选择这是什么并且应该记录它。 GCC 允许您使用标志 -fexec-charset=charset 设置执行编码,但我认为默认使用 UTF-8,MSVC 使用系统语言设置中配置的机器的“非 Unicode 应用程序编码”(永远不能是 UTF-8) ,而 clang 无条件使用 UTF-8。

char arr[] = "I'm a nice èboi"; // All characters should be ASCII except the 'è' one, which encoding is used for this?
cout << strlen(arr); // Returns 15 as ASCII, why?

编译器执行字符集实际上根本不必与 ASCII 兼容。例如,它可能是 EBDIC。

strlen(arr) 返回 15,因为使用编译器执行字符集编码的字符串字面量为 15 个字节长。由于字符串文字长度为 15 个字符,这可能意味着编译器执行字符集对每个字符使用一个字节,包括“è”。 (并且由于 UTF-8 无法将该字符串编码为仅 15 个字节,这最终表明您的编译器没有使用 UTF-8 作为编译器执行字符集。)

char arr2[] = "I'm a niße boy"; // And what encoding is it used here?
cout << strlen(arr2); // Returns 1514, what does this mean?

编码不会根据字符串的内容而改变。编译器将始终使用执行字符集。我假设 '1514' 是一个错字,strlen(arr2) 实际上返回 14,因为该字符串中有 14 个字符,而且之前的字符串似乎每个字符也使用一个字节。

如果我在我的 VS 项目配置中选择“多字节字符集”而不是“unicode”,这是什么意思,会产生什么影响?

该设置与编译器使用的编码无关。它只是将微软标题中的宏设置为不同的东西。 TCHAR,所有在 *W 和 *A 函数之间进行选择的宏,等等。

事实上,启用“unicode”后完全可以使用多字节字符串编写程序,启用“多字节字符集”时也可以使用unicode。

如果 UTF-32 通常使用 4 个字节来编码一个字符(即使它们不需要),那么像 U+FFFF(FFFF 十六进制是十进制的 65535)这样的 unicode 代码点如何表示任何可能的 unicode 字符,如果最大值是 FFFF 吗? (http://inamidst.com/stuff/unidata/)

这个问题毫无意义。也许如果你改写...

【讨论】:

  • 你回答了所有问题,除了最后一个雷米正确回答的问题。我仍然将积分奖励给您,但在他的回答中加上 +1。谢谢!
【解决方案2】:

char 在 C++ 中保存一个 8 位值,而不管其他任何内容。因此,这些变量包含字节序列。如果它们完全是 Unicode(可能不是),那么它们就是 UTF-8。

Latin-1 集中的重音字符(例如 è)在 Unicode 中有两种表示形式:组合和分解。组合版本是一个字符,分解版本是两个。可以看http://www.fileformat.info/info/unicode/char/e8/index.htm等资源;它会告诉您您在问题中发布的字符是组合的,在 UTF-8 中它是 0xC3 0xA8 (c3a8) (两个字节)。

您也有可能在 ACP 中为 Latin1 编译,而不是在 Unicode 中,在这种情况下,所有这些字符的长度都是一个字节。

你的 strlen 1514 对我来说是不可理解的;我想知道 char[] = "xxxx" 是否没有用尾随零初始化,但我不记得另一种方式。您可以尝试将其更改为 char*,然后看到您得到不同的答案。

【讨论】:

  • strlen 的 1514 可能是因为在第一次 'cout' 调用之后 OP 没有换行,所以真正的字符串长度只有 14。
  • Banex 有道理,我很傻。对不起..感谢其余的答案,如果我一开始很粗鲁,请原谅。
  • char 不保证为 8 位
  • 在他的编译器上,不是吗?
【解决方案3】:

如果 UTF-32 通常使用 4 个字节来编码一个字符(即使它们不是必需的),那么像 U+FFFF(FFFF 十六进制是十进制的 65535)这样的 unicode 代码点如何表示任何可能的 unicode 字符,如果最大值是 FFFF 吗? (http://inamidst.com/stuff/unidata/)

您的来源已过时。在早期,当 UCS-2 是唯一的 Unicode 编码时,Unicode 被限制为 U+FFFF 的最大代码点,但几年前 Unicode 已经超出了这个限制。创建 UTF(UTF-8、UTF-16、UTF-32)来替换 UCS-2 并扩展限制,目前是代码点 U+10FFFF(UTF-16 可以编码的最高代码点)。

【讨论】:

  • 谢谢!这正是我的意思
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-12
相关资源
最近更新 更多