在 C11 中,添加了一个带有前缀
u8
的新字符串文字。这表示文本编码为 UTF-8 的字符数组。这怎么可能?普通字符不是有符号的吗?这意味着由于符号位的存在,它可以使用的信息少了一位?我的逻辑是,一串 UTF-8 文本需要是一个无符号字符数组。
普通字符不是有符号的吗?
char
是signed
还是unsigned
取决于实现。
此外,符号位并没有“丢失”,它仍然可以用来表示信息,并且
char
不一定是8位大(在某些平台上可能会更大)。
这里有一个潜在的问题:
如果带有
CHAR_BIT == 8
的实现使用char
的符号量值表示(因此char
有符号),那么当UTF-8需要位模式10000000
时,这是一个负0。所以if 该实现进一步不支持负 0,那么给定的 UTF-8 字符串可能包含无效(陷阱)值 char
,这是有问题的。即使它确实支持负零,但在 10000000
中使用 UTF-8 数据时,位模式 char
与 00000000
与位模式 char[]
(nul 终止符)的比较很容易导致问题.
我认为这意味着对于符号量级 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
(1 的补码负零)。
不,符号位还是有点!而且 UTF-8 规范本身并没有规定字符必须是无符号的。
PS Wat 是 kookwekker voor 'n naam 吗?
char 的符号并不重要; utf8 只能通过移位和掩码操作来处理(这对于有符号类型来说可能很麻烦,但并非不可能)但是:utf8 需要至少 8 位,所以“assert (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;
}