打印每个宽字符的字节的char值

时间:2016-02-11 14:45:08

标签: c size multibyte

运行以下内容时:

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及其大小,而不仅仅是对字符大小的理解。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

来自C99 standard,第6.4.4.4节:

  

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

     

...

     

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

你机器上的

sizeof(int)可能是4,这就是你得到这个结果的原因。

所以'é''c''l'都是整数字符常量,因此所有类型都是int,其大小为4.事实上有些是多字节的,有些是在这方面并不重要。