我读到C没有定义char是有符号还是无符号,并且在GCC页面中这表示它可以在x86上签名并且在PowerPPC和ARM中无符号。
Okey,我正在用GLIB编写一个程序,将char定义为gchar(不超过它,只是标准化的一种方式)。
我的问题是,UTF-8怎么样?它使用的不仅仅是一块内存吗?
说我有一个变量
unsigned char * string =“我的字符串,带有UTF8 enconding~>çã”;
如果我将变量声明为
,请参阅无符号
我只有127个值(所以我的程序会存储更多的mem块)或者UTF-8也会变为负值?
很抱歉,如果我无法正确解释,但我认为我有点复杂。
注意: 谢谢你的回答
我不明白它是如何正常解释的。
我认为就像ascii一样,如果我的程序中有一个带符号和无符号的字符,那么字符串就会有不同的值,这会导致混淆,想象一下它在utf8中。
答案 0 :(得分:6)
我有几个要求解释我发表的评论。
当您比较字符并期望某个排序时,char
类型可以默认为有符号或无符号类型这一事实可能很重要。特别是,UTF8使用高位(假设char
是8位类型,在绝大多数平台中都是如此),以指示字符代码点需要表示多个字节。 / p>
问题的一个快速而肮脏的例子:
#include <stdio.h>
int main( void)
{
signed char flag = 0xf0;
unsigned char uflag = 0xf0;
if (flag < (signed char) 'z') {
printf( "flag is smaller than 'z'\n");
}
else {
printf( "flag is larger than 'z'\n");
}
if (uflag < (unsigned char) 'z') {
printf( "uflag is smaller than 'z'\n");
}
else {
printf( "uflag is larger than 'z'\n");
}
return 0;
}
在我工作的大多数项目中,通常使用明确指定char
的typedef来避免使用未加修饰的unsigned char
类型。类似uint8_t
或
stdint.h
typedef unsigned char u8;
一般来说处理unsigned char
类型似乎运行良好并且几乎没有问题 - 我偶然遇到的一个问题是使用那种类型的东西来控制循环:
while (uchar_var-- >= 0) {
// infinite loop...
}
答案 1 :(得分:5)
使用unsigned char有其优点和缺点。最大的好处是你没有得到符号扩展或其他有趣的功能,如签名溢出,这会产生意外的计算结果。无符号字符也与&lt; cctype&gt;兼容宏/函数,如isalpha(ch)(所有这些都需要unsigned char范围内的值)。另一方面,所有I / O函数都需要char *,只要你进行I / O操作就需要进行转换。
对于UTF-8,将它存储在有符号或无符号数组中是可以的,但是你必须小心那些字符串文字,因为它们几乎不能保证它们是有效的UTF-8。 C ++ 0x添加了UTF-8字符串文字以避免可能出现的问题,我希望下一个C标准也可以采用这些文字。
一般情况下,只要确保源代码文件始终采用UTF-8编码,就应该没问题。
答案 2 :(得分:4)
两件事:
char类型是有符号还是无符号不会影响您将UTF8编码字符串转换为您正在使用的任何显示字符串类型(WCHAR或其他)的能力。不要担心,换句话说:UTF8字节只是字节,无论你使用什么作为编码器/解码器都会做正确的事情。
您的一些困惑可能是您尝试这样做:
unsigned char *string = "This is a UTF8 string";
不要这样做 - 你混合了不同的概念。 UTF-8编码的字符串只是一个字节序列。 C字符串文字(如上所述)并没有真正用于表示这一点;它们旨在表示“ASCII编码”字符串。虽然在某些情况下(比如我的),它们最终会成为同一个东西,但在问题的例子中,它们可能不会。当然在其他情况下他们不会。从外部资源加载Unicode字符串。一般来说,我要警惕在.c源文件中嵌入非ASCII字符;即使编译器知道如何处理它们,工具链中的其他软件也可能不会。
答案 3 :(得分:2)
signed / unsigned只影响算术运算。如果char是无符号的,那么更高的值将是正数。如果签字,他们将是负面的。但范围仍然相同。
答案 4 :(得分:1)
实际上,unsigned
/ signed
未指定变量可容纳的值。它指定了解释的方式。
因此,unsigned char
与signed char
具有相同数量的值,除了一个具有负数而另一个不具有负数。它仍然是8位(如果我们假设char
保持8位,我不确定它到处都有。)
答案 5 :(得分:1)
将char *用作字符串时没有区别。签名/未签名的唯一时间会产生影响,如果您将其解释为数字,例如算术,或者您将其打印为整数。
答案 6 :(得分:0)
UTF-8个字符存储在一个字节中。 UTF-8字符可以是1-4字节宽。因此,char
,wchar_t
,signed
或unsigned
不足以假设一个单位总是可以存储一个UTF-8字符。
大多数平台(例如PHP,.NET等)都可以正常构建字符串(例如C中的char[]
)并使用库在字符串之间转换编码和解析字符。 / p>
答案 7 :(得分:0)
关于你的问题:
如果我有一个烧焦或未签名的字符阵列可以让我的程序运行错误? - drigoSkalWalker
是。我做了。如果使用普通的签名字符,那么从我的应用程序中看到一个简单的可运行的摘录,完全出错了。 将所有字符更改为无符号in参数后尝试运行它。像这样:
int is_valid( unsigned char c);
然后它应该正常工作。
#include <stdio.h>
int is_valid(char c);
int main() {
char ch = 0xFE;
int ans = is_valid(ch);
printf("%d", ans);
}
int is_valid(char c) {
if((c == 0xFF) || (c == 0xFE)) {
printf("NOT valid\n");
return 0;
}
else {
printf("valid\n")
return 1;
}
}
它的作用是验证char是否是utf-8中的有效字节。 0xFF和0xFE在utf-8中不是有效字节。 如果函数将其验证为有效字节,请设想问题?
这是怎么回事:
0xFE
=
11111110
=
254
如果将其保存在普通字符(已签名)中,则最左边的位(最高位)使其为负数。但它的负数是多少?
它通过翻转位并添加一位来实现。
11111110
00000001
00000001 + 00000001 =
00000010 = 2
并且记住它使它变为负数,因此变为-2
所以(-2 == 0xFE)在函数中是不正确的。 同样适用于(-2 == 0xFF)。
因此,检查无效字节的函数最终会验证无效字节,就像它们没问题一样:-o。
在处理utf-8时,我可以想到坚持无符号的另外两个原因是:
如果您可能需要向右移位一些,可能会有麻烦,因为如果使用签名字符,您最终可能会从左侧添加1。
utf-8和unicode只使用正数,所以...为什么不这样做?保持简单:)