在 UTF8 中,我使用这个函数来计算字符(不是字节):
int schars(const char *s)
{
int i = 0;
while (*s) {
if ((*s & 0xc0) != 0x80) i++;
s++;
}
return i;
}
这是否适用于 plainchar
的实现unsigned char
?
在 UTF8 中,我使用这个函数来计算字符(不是字节):
int schars(const char *s)
{
int i = 0;
while (*s) {
if ((*s & 0xc0) != 0x80) i++;
s++;
}
return i;
}
这是否适用于 plainchar
的实现unsigned char
?
它在未签名时和char
已签名时一样有效。
在有符号 2 的补码表示和无符号表示中,UTF8 代码单元的第 8 位和第 7 位10
当且仅当代码单元不是代码点的第一个代码单元时。因此,您为每个代码点的第一个代码单元计算 1。
int
不保证是一个足够大的类型来包含每个字符串中的字符数,但我假设你不在乎;-)
“字符”可能是一个模棱两可的术语。此代码计算 Unicode 代码点,这与可显示字符(“字形”)不同。有时多个代码点代表一个字素,例如当组合标记用于重音时。了解 Unicode 字符串中有多少个代码点的唯一实际用途是计算编码为 UTF-32 时它将占用多少字节。如果您小心,您可以确保唯一需要处理“字符”的代码是字体引擎,以及一些复杂的操作,例如 Unicode 规范化和字符编码。
它应该。
您只使用二元运算符,并且无论底层数据类型是有符号还是无符号,它们的功能都相同。唯一的例外可能是!=
运算符,但您可以用 a 替换它&
,然后用 a 来包含整个事物!
,ala:
!((*s & 0xc0) & 0x80)
然后你只有二元运算符。
您可以通过检查ANSI C 标准的第 3.3.10 节来验证字符是否提升为整数,该节规定“每个操作数 [按位与] 都应具有整数类型。”
编辑
我修改我的答案。根据 ANSI C 标准的 3.3,有符号的位运算与无符号的位运算不同:
一些运算符(一元运算符 ~ 和二元运算符 << 、 >> 、 & 、 ^ 和 | 统称为按位运算符)应具有整数类型的操作数。这些运算符返回的值取决于整数的内部表示,因此具有符号类型的实现定义方面。
事实上,对有符号整数执行按位运算在这里被列为可能的安全漏洞。
在 Visual Studio 编译器中,有符号和无符号的处理方式相同(参见此处)。
正如这个 SO question所讨论的,最好使用unsigned char
按字节读取内存和操作内存。
是的,它会的。
*s
将int
在计算发生之前提升。因此,您的代码相当于:
if (((int) *s & 0xC0) != 0x80) i++;
即使char
未签名,上述内容也将起作用。