代码之家  ›  专栏  ›  技术社区  ›  Marco A.

C/C++Unicode字符编码大小和默认格式

  •  2
  • Marco A.  · 技术社区  · 10 年前

    我刚刚意识到(多亏了我的大学课程)我以为我知道的关于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编码,我想(?)这一点也不清楚。

    有人能帮我吗 清晰的解释 对于上述问题?

    3 回复  |  直到 10 年前
        1
  •  6
  •   bames53    10 年前
        char arr1[] = "I am a nice boy"; // Is this stored as UTF-8 (multi-byte) or ASCII?
    

    这存储在编译器的执行字符集中。编译器可以选择这是什么,并将其记录下来 -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”,这意味着什么?这会产生什么影响?

    该设置与编译器使用的编码无关。它只是将Microsoft标题中的宏设置为不同的内容。TCHAR、在*W和*A函数之间选择的所有宏等。

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

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

    这个问题毫无意义。也许如果你换个说法。。。

        2
  •  1
  •   bmargulies    10 年前

    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中编译,在这种情况下,所有这些字符的长度都是一个字节。

    我无法理解你1514年的故事;我想知道char[]=“xxxx”是否没有使用尾随零进行初始化,但我不记得其中一种方式。你可以试着把它们改成 char* 相反,你会得到不同的答案。

        3
  •  1
  •   Remy Lebeau    10 年前

    如果UTF-32通常使用4个字节来编码一个字符(即使不需要),那么如果最大值为FFFF,那么像U+FFFF(FFFF十六进制为十进制65535)这样的unicode码点如何表示任何可能的unicode字符?( 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可以编码的最高码点)。