【问题标题】:printing the char value of each wide character's bytes打印每个宽字符字节的 char 值
【发布时间】:2016-05-22 09:52:50
【问题描述】:

运行以下内容时:

char acute_accent[7] = "éclair";
int i;
for (i=0; i<7; ++i)
{
    printf("acute_accent[%d]: %c\n", i, acute_accent[i]);
}

我明白了:

acute_accent[0]: 
acute_accent[1]: �
acute_accent[2]: c
acute_accent[3]: l
acute_accent[4]: a
acute_accent[5]: i
acute_accent[6]: r

这让我觉得多字节字符 é 是 2 字节宽。

但是,在运行此程序时(在忽略来自multi-character character constant 的编译器警告我之后):

printf("size: %lu",sizeof('é'));

我收到size: 4

大小不一的原因是什么?

编辑:这个问题与this 不同,因为它更多的是关于多字节字符编码、不同的 UTF 及其大小,而不是仅仅了解 char 的大小。

【问题讨论】:

  • ' 引号中的常量属于int 类型。不要忽视警告。
  • 什么平台?在 Windows 上,您可以使用 UCS-2 wchar_t,但您仍然面临复合代码点和代理对的缓冲区溢出风险。您还应该指定字符串的编码,否则实现未定义:u8"éclair";。可能重复:stackoverflow.com/questions/2172943
  • "在忽略编译器警告之后" - 这已经足够了。如果你不完全理解为什么编译器会发出警告,你不应该忽略它。
  • @EugeneSh。和奥拉夫,吸取教训,谢谢。

标签: c size multibyte


【解决方案1】:

来自C99 standard,第 6.4.4.4 节:

2 整数字符常量是一个或多个多字节的序列 用单引号括起来的字符,如 'x'。

...

10 整数字符常量的类型为 int。

您机器上的sizeof(int) 可能是 4,这就是您得到该结果的原因。

所以'é''c''l'都是整数字符常量,所以都是int类型,大小为4。有些是多字节的,有些不是,这无关紧要尊重。

【讨论】:

  • 但是什么是“一个整数字符常量”?
  • @PaulOgilvie 添加了更多详细信息。
  • @dbush,谢谢,还有一个后续问题:é 在我的机器(ubuntu 14.04,64 位)上明显超过 2 个字节。但它不应该是 4 个字节吗?
【解决方案2】:

您看到差异的原因是因为在您的第一个示例中,字符 é 被编译器编码为两字节 UTF-8 代码点 0xC3 0xA9

看这里:

http://www.fileformat.info/info/unicode/char/e9/index.htm

如 dbush 所述,字符 'é' 被编码为 UTF-32 代码点并存储在整数中;因此它被表示为四个字节。

您的部分困惑源于通过以未定义的方式存储 Unicode 来使用实现定义的功能。

为了防止未定义的行为,您应该始终清楚地识别字符串文字的编码类型。

例如:

char acute_accent[7] = u8"éclair"

这是非常糟糕的形式,因为除非你自己数出来,否则你无法知道字符串的确切长度,除非。事实上,我的编译器 (g++) 对我大喊大叫,因为虽然字符串是 7 个字节,但它总共有 8 个字节,最后是空字符。所以你实际上已经超出了缓冲区。

改用这个更安全:

const char* acute_accent = u8"éclair"

注意你的字符串实际上是 8 字节:

#include <stdio.h>
#include <string.h> // strlen

int main() {
    const char* a = u8"éclair";

    printf("String length : %lu\n", strlen(a));

    // Add +1 for the null byte
    printf("String size   : %lu\n", strlen(a) + 1);

    return 0;
}

输出是:

String length : 7
String size   : 8

还要注意字符的大小在 C 和 C++ 之间是不同的!!

#include <stdio.h>

int main() {
    printf("%lu\n", sizeof('a'));

    printf("%lu\n", sizeof('é'));

    return 0;
}

在 C 中的输出是:

4
4

在 C++ 中,输出是:

1
4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-01
    • 2016-10-29
    • 2020-02-01
    • 2023-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多