[英]What is an unsigned char?
在 C/C++ 中, unsigned char
有什么用? 它与普通的char
有何不同?
在 C++ 中,存在三种不同的字符类型:
char
signed char
unsigned char
如果您对text使用字符类型,请使用不合格的char
:
'a'
或'0'
。"abcde"
它也可以作为数字值计算,但未指定该值被视为有符号还是无符号。 当心通过不等式进行字符比较 - 尽管如果您将自己限制为 ASCII (0-127),那么您就很安全了。
如果您使用字符类型作为数字,请使用:
signed char
,它至少给你 -127 到 127 的范围。 (-128 到 127 是常见的)unsigned char
,它至少为您提供0 到 255 的范围。 “至少”,因为 C++ 标准只给出了每个数字类型需要覆盖的最小范围的值。 sizeof (char)
需要为 1(即一个字节),但理论上一个字节可以是例如 32 位。 sizeof
仍然会报告它的大小为1
- 这意味着你可以有sizeof (char) == sizeof (long) == 1
。
这是依赖于实现的,因为 C 标准没有定义char
的符号。 根据平台的不同, char 可能是signed
或unsigned
,因此如果您的实现依赖于它,您需要明确要求signed char
或unsigned char
。 如果您打算表示字符串中的字符,只需使用char
,因为这将匹配您的平台放入字符串中的内容。
有signed char
和unsigned char
之间的区别正如您所期望的。 在大多数平台上, signed char
将是一个 8 位二进制补码,范围从-128
到127
,而unsigned char
将是一个 8 位无符号整数( 0
到255
)。 注意标准不要求char
类型有 8 位,只有sizeof(char)
返回1
。 您可以在limits.h
使用CHAR_BIT
获取字符中的位数。 不过,今天几乎没有平台会是8
以外的平台。
有这个问题的一个很好的总结在这里。
正如其他人在我发布这篇文章后提到的int8_t
,如果您真的想表示小整数,最好使用int8_t
和uint8_t
。
因为我觉得真的很需要,所以我只想说明一些C和C++的规则(在这方面它们是相同的)。 首先,所有unsigned char
位都参与确定任何 unsigned char 对象的值。 其次, unsigned char
被明确声明为无符号。
现在,我与某人讨论了将 int 类型的值-1
转换为unsigned char
时会发生什么。 他拒绝了结果unsigned char
所有位都设置为 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;
它也遵循转换不只是截断高阶位。 二进制补码的幸运事件是它只是在那里截断,但对于其他符号表示不一定如此。
例如unsigned char 的用法:
unsigned char
通常用于计算机图形中,它经常(尽管并非总是)为每个颜色分量分配一个字节。 通常看到 RGB(或 RGBA)颜色表示为 24(或 32)位,每个位都是一个unsigned char
。 由于unsigned char
值落在 [0,255] 范围内,因此这些值通常被解释为:
所以你最终会得到 RGB 红色为 (255,0,0) -> (100% 红色,0% 绿色,0% 蓝色)。
为什么不使用signed char
? 算术和位移位变得有问题。 如前所述,有signed char
的范围基本上移动了 -128。 将 RGB 转换为灰度的一种非常简单和幼稚(大部分未使用)的方法是对所有三个颜色分量求平均值,但是当颜色分量的值为负时,这会遇到问题。 使用unsigned char
算术时,红色 (255, 0, 0) 平均为 (85, 85, 85)。 但是,如果这些值是有signed char
(127,-128,-128),我们最终会得到 (-99, -99, -99),在我们的unsigned char
空间中将是 (29, 29, 29) ,这是不正确的。
如果要将字符用作小整数,最安全的方法是使用int8_t
和uint8_t
类型。
unsigned char
只取正值......比如0到255
然而
signed char
采用正值和负值......比如-128到+127
signed char
范围是 -128 到 127; unsigned char
范围是 0 到 255。
char
将等价于有符号字符或无符号字符,具体取决于编译器,但它是一种不同的类型。
如果您使用 C 风格的字符串,只需使用char
。 如果您需要将字符用于算术(很少见),请明确指定有符号或无符号以实现可移植性。
char
和unsigned char
不能保证在所有平台上都是 8 位类型——它们保证是 8 位或更大。 某些平台具有9 位、32 位或 64 位字节。 但是,当今最常见的平台(Windows、Mac、Linux x86 等)具有 8 位字节。
unsigned char
是无符号字节值(0 到 255)。 您可能认为char
是一个“字符”,但它实际上是一个数值。 常规char
是有符号的,因此您有 128 个值,这些值使用 ASCII 编码映射到字符。 但无论哪种情况,您在内存中存储的都是一个字节值。
就直接值而言,当已知值在CHAR_MIN
和CHAR_MAX
之间时使用常规字符, CHAR_MAX
符号字符在正端提供两倍的范围。 例如,如果CHAR_BIT
为 8,则常规char
的范围只能保证为 [0, 127](因为它可以有符号或无符号),而unsigned char
将是 [0, 255],而有signed char
将是 [-127] , 127]。
就其用途而言,标准允许 POD(纯旧数据)的对象直接转换为无符号字符数组。 这允许您检查对象的表示和位模式。 char 或signed char 不存在相同的安全类型双关保证。
如果您喜欢使用各种类型的特定长度和符号,那么使用uint8_t
、 int8_t
、 uint16_t
等可能会更好,因为它们完全按照他们所说的去做。
unsigned char
是所有小技巧的核心。 在几乎所有平台的所有编译器中, unsigned char
只是一个字节和一个(通常)8 位的无符号整数,可以被视为一个小整数或一组位。
成瘾,正如其他人所说,标准没有定义字符的符号。 所以你有 3 种不同的char
类型: char
、 signed char
、 unsigned char
。
unsigned char
只取正值:0 到 255,而signed char
取正值和负值:-128 到 +127。
一些谷歌搜索发现了这个,人们对此进行了讨论。
无符号字符基本上是一个字节。 因此,如果您需要一个字节的数据,您将使用它(例如,您可能想使用它来设置要传递给函数的标志打开和关闭,就像在 Windows API 中经常做的那样)。
无符号字符使用为常规字符的符号保留的位作为另一个数字。 这会将范围更改为 [0 - 255],而不是 [-128 - 127]。
当您不需要符号时,通常使用无符号字符。 在将 char 作为字节处理而不是将其用作数字时,这将在执行诸如移位(移位扩展符号)之类的操作和其他操作时有所不同。
引用自《c 编程语言》一书:
限定符有signed
或unsigned
可应用于 char 或任何整数。 无符号数总是正数或零,并遵守算术模 2^n 的法则,其中 n 是类型中的位数。 因此,例如,如果字符是 8 位,则无符号字符变量的值介于 0 和 255 之间,而有符号字符的值介于 -128 和 127 之间(在二进制补码机中)。纯字符是有符号还是无符号是机器依赖,但可打印的字符总是正数。
signed char
和unsigned 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.