char []如何表示UTF-8字符串?

时间:2012-01-11 11:42:29

标签: c string utf-8 c11

在C11中,添加了一个带有前缀u8的新字符串文字。这将返回一个字符数组,其中文本编码为UTF-8。这怎么可能呢?签名不是正常的char吗?这意味着由于符号位,它使用的信息少了一点?我的逻辑将描述一串UTF-8文本需要是一个无符号字符数组。

4 个答案:

答案 0 :(得分:6)

  

签名不是普通的char吗?

依赖于实现,charsigned还是unsigned

此外,符号位不会“丢失”,它仍可用于表示信息,而char不一定是8位大(在某些平台上可能更大)。

答案 1 :(得分:6)

这里有一个潜在的问题:

如果 CHAR_BIT == 8的实施使用char的符号幅度表示(因此char已签名),那么当UTF-8需要位时模式10000000,这是负0.所以如果实现进一步不支持负0,那么给定的UTF-8字符串可能包含{{1}的无效(陷阱)值},这是有问题的。即使它确实支持负零,位模式char比较等于10000000到位模式char(nul终结符)的事实在使用UTF-8时也容易引起问题00000000中的数据。

我认为这意味着对于符号级别的C11实现,char[]需要是无符号的。通常由char签名或无符号来实现,但当然如果char被签名导致无法正确实现UTF-8文字,那么实现者只需选择无符号。顺便说一句,对于C ++的非2的补码实现一直如此,因为C ++允许char以及char用于访问对象表示。 C只允许unsigned char

在2的补码和1的补码中,UTF-8数据所需的位模式是unsigned char的有效值,因此实现可以使signed char自由签名或无符号且仍然可以在char中表示UTF-8字符串。这是因为所有256位模式都是有效的2的补码值,而UTF-8恰好不使用字节char[](1s'补充负零)。

答案 2 :(得分:1)

不,一点符号仍然有点!而UTF-8规范本身并没有说字符必须是无符号的。

PS Wat是kookwekker voor'n naam?

答案 3 :(得分:1)

char的签名并不重要; utf8只能通过移位和掩码操作来处理(这对于签名类型来说可能很麻烦,但并非不可能)但是:utf8 需要至少8位,所以"断言(CHAR_BIT> = 8);"

为了说明这一点:以下片段不包含对字符值的算术运算,只包含shift& mask。

static int eat_utf8(unsigned char *str, unsigned len, unsigned *target)
{
unsigned val = 0;
unsigned todo;

if (!len) return 0;

val = str[0];
if ((val & 0x80) == 0x00) { if (target) *target = val; return 1; }
else if ((val & 0xe0) == 0xc0) { val &= 0x1f; todo = 1; }
else if ((val & 0xf0) == 0xe0) { val &= 0x0f; todo = 2; }
else if ((val & 0xf8) == 0xf0) { val &= 0x07; todo = 3; }
else if ((val & 0xfc) == 0xf8) { val &= 0x03; todo = 4; }
else if ((val & 0xfe) == 0xfc) { val &= 0x01; todo = 5; }
else {  /* Default (Not in the spec) */
        if (target) *target = val;
        return -1; }


len--;str++;
if (todo > len) { return -todo; }

for(len=todo;todo--;) {
        /* For validity checking we should also
        ** test if ((*str & 0xc0) == 0x80) here */
        val <<= 6;
        val |= *str++ & 0x3f;
        }

if (target) *target = val;
return  1+ len;
}