什么是unsigned char?

在C/ c++中,unsigned char被用来做什么?它与常规的char有什么不同?

690512 次浏览

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

signed charunsigned char之间的区别正如你所期望的那样。在大多数平台上,signed char将是一个8位的二补数,范围从-128127,而unsigned char将是一个8位无符号整数(0255)。注意标准并不要求char类型有8位,只要求sizeof(char)返回unsigned char0。你可以在unsigned char2中使用unsigned char1获取一个char的比特数。然而,今天很少有平台会使用unsigned char3以外的东西。

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

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

signed char的范围是-128到127;unsigned char的范围是0到255。

char将等同于有符号char或无符号char,这取决于编译器,但它是一种不同的类型。

如果你使用c风格的字符串,只需使用char。如果需要使用字符进行算术运算(非常少见),请显式指定signed或unsigned以实现可移植性。

一些人在谷歌上找到了,在那里人们对此进行了讨论。

无符号字符基本上是一个单字节。所以,如果你需要一个字节的数据,你可以使用它(例如,也许你想用它来设置标志的开启和关闭,以传递给一个函数,就像在Windows API中经常做的那样)。

unsigned char是一个无符号字节值(0到255)。你可能认为char是一个“字符”,但它实际上是一个数值。常规的char是有符号的,所以你有128个值,这些值映射到使用ASCII编码的字符。但无论哪种情况,您在内存中存储的都是字节值。

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

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

如果你喜欢使用各种类型的特定长度和符号,你可能更适合使用uint8_tint8_tuint16_t等,因为它们完全符合它们所说的。

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

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

unsigned char是所有比特诡计的核心。几乎在所有平台的所有编译器中,unsigned char只是一个字节和一个无符号整数(通常为8位),可以被视为一个小整数或一组位。

此外,正如其他人所说,标准并没有定义char的符号。所以你有3种不同的char类型:charsigned charunsigned char

例如无符号字符的用法:

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

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

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

为什么不使用signed char?算术和位移位成为问题。如前所述,signed char的范围本质上被移动了-128。将RGB转换为灰度的一种非常简单和幼稚(通常不使用)的方法是平均所有三种颜色成分,但当颜色成分的值为负时,这就会遇到问题。当使用unsigned char算术时,Red(255,0,0)平均为(85,85,85)。然而,如果值是__abc0(127,-128,-128),我们最终会得到(-99,-99,-99),这将是(29,29,29)在我们的unsigned char空间,这是不正确的。

charunsigned char在所有平台上都不保证是8位类型;它们保证是8位或更大的类型。一些平台有9位、32位或64位字节。然而,今天最常见的平台(Windows、Mac、Linux x86等)都有8位字节。

在c++中,有三种截然不同的字符类型:

  • char
  • signed char
  • unsigned char

如果你正在为文本使用字符类型,请使用非限定的char:

  • 它是像'a''0'这样的字符字面量的类型(仅在c++中,在C中它们的类型是int)
  • 它是构成像"abcde"这样的C字符串的类型

它也是一个数字值,但是没有指定该值是有符号还是无符号。小心通过不平等进行字符比较——尽管如果你将自己限制在ASCII(0-127),你是安全的。

如果你使用字符类型数字,使用:

  • signed char,它给你至少 -127到127的范围。(-128到127是常见的)
  • unsigned char,它给你至少 0到255的范围。

至少,因为c++标准只给出了每个数字类型需要涵盖的最小值范围。sizeof (char)必须是1(即一个字节),但一个字节在理论上可以是32位。__ABC1的大小仍然报告为1 -意思是你可以sizeof (char) == sizeof (long) == 1

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

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

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

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

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

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

unsigned char c = (unsigned char)-1;

也就是说,转换为只是截断高阶位。二进制补码的幸运之处在于它只是一个截断符,但对于其他符号表示则不一定如此。

unsigned char只取正值....比如0255

signed char取正负值....比如-128年+ 127

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

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

unsigned char只取正值:0到255 while signed char取正负值:-128到+127

signed charunsigned char都表示1字节,但是它们有不同的范围。

   Type        |      range
-------------------------------
signed char    |  -128 to +127
unsigned char  |     0 to 255

signed char中,如果我们考虑char letter = 'A', 'A'表示ASCII/Unicode中65的二进制,如果65可以存储,则-65也可以存储。在ASCII/Unicode中没有负二进制值,因此不需要担心负数。

例子

#include <stdio.h>


int main()
{
signed char char1 = 255;
signed char char2 = -128;
unsigned char char3 = 255;
unsigned char char4 = -128;


printf("Signed char(255) : %d\n",char1);
printf("Unsigned char(255) : %d\n",char3);


printf("\nSigned char(-128) : %d\n",char2);
printf("Unsigned char(-128) : %d\n",char4);


return 0;
}

输出-:

Signed char(255) : -1
Unsigned char(255) : 255


Signed char(-128) : -128
Unsigned char(-128) : 128