在 C11 中,添加了一个带有前缀 u8 的新字符串文字。这将返回一个字符数组,其中文本编码为 UTF-8。这怎么可能?不是普通的字符签名吗?意味着由于符号位,它可以使用的信息少一点吗?我的逻辑将描述一串 UTF-8 文本需要是一个无符号字符数组。
4 回答
不是普通的字符签名吗?
char
是signed
还是取决于实现unsigned
。
此外,符号位不会“丢失”,它仍然可以用来表示信息,并且char
不一定是 8 位大(在某些平台上可能更大)。
这里有一个潜在的问题:
如果一个实现CHAR_BIT == 8
使用符号大小表示char
(sochar
是有符号的),那么当 UTF-8 需要 bit-pattern10000000
时,这是一个负 0。所以如果实现进一步不支持负 0,那么一个给定的 UTF-8 字符串可能包含 的无效(陷阱)值char
,这是有问题的。即使它确实支持负零,10000000
当在.char
00000000
char[]
我认为这意味着对于符号幅度 C11 实现,char
需要无符号。通常,是否char
有符号或无符号取决于实现,但当然,如果char
被签名导致无法正确实现 UTF-8 文字,那么实现者只需要选择无符号即可。顺便说一句,C++ 的非 2 补码实现一直都是这种情况,因为 C++ 允许char
以及unsigned char
用于访问对象表示。C 只允许unsigned char
.
在 2 的补码和 1 的补码中,UTF-8 数据所需的位模式是 的有效值signed char
,因此实现可以自由地制作char
有符号或无符号,并且仍然能够在 中表示 UTF-8 字符串char[]
。这是因为所有 256 位模式都是有效的 2 补码值,而 UTF-8 恰好不使用该字节11111111
(1s 补码负零)。
不,符号位仍然有点!并且 UTF-8 规范本身并没有说字符必须是无符号的。
PS Wat is kookwekker voor 'n naam?
char 的符号无关紧要;utf8 只能通过移位和掩码操作来处理(这对于有符号类型可能很麻烦,但并非不可能)但是:utf8至少需要8 位,因此“断言(CHAR_BIT >= 8);”
逐点说明:以下片段不包含对字符值的算术运算,仅包含移位和掩码。
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;
}