在C/ c++中,unsigned char是用来干什么的?它和常规char有什么不同?


当前回答

摘自《c语言编程》一书:

有符号或无符号限定词可以应用于char或任何整数。无符号数 都是正的或零的,并且服从对2^n取模的算术法则,其中n是数字 类型中的位。例如,如果字符是8位,unsigned char变量就有值 在0到255之间,而有符号字符的值在-128到127之间 补机)。纯字符是有符号字符还是无符号字符取决于机器, 但是可打印的字符总是正的。

其他回答

例如unsigned char的用法:

Unsigned char经常用于计算机图形,它经常(虽然不总是)为每个颜色组件分配一个字节。通常可以看到RGB(或RGBA)颜色表示为24(或32)位,每个位都是unsigned char。由于unsigned char值落在[0,255]范围内,这些值通常被解释为:

0表示完全缺乏给定的颜色组件。 255表示某一特定色素的100%。

所以你最终会得到RGB红色为(255,0,0)->(100%红,0%绿,0%蓝)。

Why not use a signed char? Arithmetic and bit shifting becomes problematic. As explained already, a signed char's range is essentially shifted by -128. A very simple and naive (mostly unused) method for converting RGB to grayscale is to average all three colour components, but this runs into problems when the values of the colour components are negative. Red (255, 0, 0) averages to (85, 85, 85) when using unsigned char arithmetic. However, if the values were signed chars (127,-128,-128), we would end up with (-99, -99, -99), which would be (29, 29, 29) in our unsigned char space, which is incorrect.

就直接值而言,当已知值在CHAR_MIN和CHAR_MAX之间时,使用常规char,而unsigned char在正端提供了两倍的范围。例如,如果CHAR_BIT为8,则常规char的范围只能保证为[0,127](因为它可以是有符号的或无符号的),而无符号char将是[0,255],而有符号char将是[-127,127]。

就其用途而言,标准允许将POD(普通旧数据)对象直接转换为unsigned char数组。这允许您检查对象的表示和位模式。对于char或signed char,不存在安全类型双关的相同保证。

无符号字符使用为常规字符的符号保留的位作为另一个数字。这将范围更改为[0 - 255],而不是[-128 - 127]。

当你不想要符号时,通常使用无符号字符。这在处理像移位位(移位扩展符号)和其他将字符作为字节处理而不是将其作为数字处理时会产生不同。

因为我觉得这真的很有必要,所以我只想说明C和c++的一些规则(在这方面它们是相同的)。首先,unsigned char的所有位都参与确定unsigned char对象的值。其次,unsigned char显式声明为unsigned。

现在,我和别人讨论过当你把int类型的值-1转换为unsigned char时会发生什么。他拒绝将生成的unsigned char的所有位都设置为1,因为他担心符号表示。但他不必如此。根据这条规则,转换会立即执行预期的操作:

如果新类型是无符号的,则通过在新类型中可以表示的最大值的基础上重复加或减1来转换值,直到该值在新类型的范围内。(C99草案中的6.3.1.3p2)

这是一种数学描述。c++用模演算来描述它,这也符合同样的规则。不管怎样,不能保证的是整数-1中的所有位在转换前都是1。那么,我们有什么可以声明结果unsigned char的所有CHAR_BIT位都变成1呢?

所有位都参与确定它的值——也就是说,对象中没有填充位。 只添加一次UCHAR_MAX+1到-1将产生一个范围内的值,即UCHAR_MAX

事实上,这就够了!所以当你想让一个unsigned char的所有位都是1时,你可以这样做

unsigned char c = (unsigned char)-1;

由此可见,转换不仅仅是截断高阶位。幸运的是,对于2的补数来说,它只是一个截断,但对于其他符号表示来说,情况并不一定如此。

这取决于实现,因为C标准没有定义char的符号性。根据平台的不同,char可能是有符号的,也可能是无符号的,因此如果您的实现依赖于它,则需要显式地请求有符号char或无符号char。如果您打算表示字符串中的字符,则使用char,因为这将与您的平台在字符串中放入的内容相匹配。

有符号char和无符号char之间的区别正如您所期望的那样。在大多数平台上,signed char将是一个8位的2补数,范围从-128到127,unsigned char将是一个8位的无符号整数(0到255)。注意标准并不要求char类型有8位,只要求sizeof(char)返回1。你可以在limited .h中使用CHAR_BIT获取一个char的比特数。然而,如今很少有平台会使用8以外的东西。

这里对这个问题有一个很好的总结。

正如其他人在我发布这篇文章后提到的,如果你真的想表示小整数,你最好使用int8_t和uint8_t。