在C11中,添加了一个带有前缀u8的新字符串文字。这将返回一个字符数组,其中文本编码为UTF-8。这怎么可能呢?签名不是正常的char吗?这意味着由于符号位,它使用的信息少了一点?我的逻辑将描述一串UTF-8文本需要是一个无符号字符数组。
答案 0 :(得分:6)
签名不是普通的char吗?
依赖于实现,char
是signed
还是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;
}