题
在 C/C++ 中,什么是 unsigned char
是用来?和普通的有什么不同 char
?
解决方案
在C++中,有以下三种 清楚的 字符类型:
char
signed char
unsigned char
如果您使用字符类型 文本, ,使用不合格的 char
:
- 它是字符文字的类型,例如
'a'
或者'0'
. - 它是构成 C 字符串的类型,例如
"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
. 。根据平台的不同,字符可能是 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
. 。您可以使用以下命令获取字符中的位数 CHAR_BIT
在 limits.h
. 。如今,几乎没有什么平台可以做到这一点 8
, , 尽管。
这个问题有一个很好的总结 这里.
正如我发布此文后其他人提到的那样,您最好使用 int8_t
和 uint8_t
如果你真的想表示小整数。
因为我觉得确实有必要,所以我只想陈述一下 C 和 C++ 的一些规则(在这方面它们是相同的)。第一的, 所有位 的 unsigned char
如果有任何 unsigned char 对象,则参与确定值。第二, unsigned char
明确指出未签名。
现在,我与某人讨论了转换值时会发生什么 -1
int 类型到 unsigned char
. 。他拒绝接受由此产生的想法 unsigned char
将其所有位设置为 1,因为他担心符号表示。但他不必这样做。遵循此规则,转换将立即执行预期操作:
如果新类型未签名,则通过反复添加或减去一个比新类型中可以表示的最大值的多重复来转换值,直到该值在新类型的范围内为止。(
6.3.1.3p2
在 C99 草案中)
这是一个数学描述。C++ 用模微积分来描述它,并得出相同的规则。无论如何,什么是 不是 保证的是整数中的所有位 -1
是转换前的一个。那么,我们有什么可以声称得到的结果 unsigned char
拥有其全部 CHAR_BIT
位变为 1?
- 所有位都参与确定其值 - 也就是说,对象中不会出现填充位。
- 仅添加一次
UCHAR_MAX+1
到-1
将产生一个范围内的值,即UCHAR_MAX
其实这就够了!所以每当你想要拥有一个 unsigned char
让它的所有位都为一,你就可以
unsigned char c = (unsigned char)-1;
还可以得出转换是 不是 只是截断高阶位。的幸运事件 二进制补码 是它只是一个截断,但对于其他符号表示来说不一定如此。
至于示例用法 无符号字符:
无符号字符 经常用于计算机图形学,它经常(尽管并非总是)为每个颜色分量分配一个字节。通常看到 RGB(或 RGBA)颜色表示为 24(或 32)位,每个位代表一个颜色。 无符号字符. 。自从 无符号字符 值落在 [0,255] 范围内,这些值通常解释为:
- 0 表示完全缺少给定的颜色分量。
- 255 表示 100% 的给定颜色颜料。
所以最终得到的 RGB 红色为 (255,0,0) -> (100% 红色, 0% 绿色, 0% 蓝色)。
为什么不使用一个 签名字符?算术和位移变得有问题。正如已经解释过的,一个 签名字符的范围基本上移动了 -128。将 RGB 转换为灰度的一种非常简单且幼稚(大部分未使用)的方法是对所有三个颜色分量进行平均,但是当颜色分量的值为负时,这会遇到问题。使用时红色 (255, 0, 0) 平均为 (85, 85, 85) 无符号字符 算术。但是,如果这些值为 签名字符s (127,-128,-128),我们最终会得到 (-99, -99, -99),这将是我们的 (29, 29, 29) 无符号字符 空间,这是不正确的。
如果您想将字符用作小整数,最安全的方法是使用 int8_t
和 uint8_t
类型。
signed char
范围为 -128 到 127; unsigned char
范围为 0 到 255。
char
将相当于有符号字符或无符号字符,具体取决于编译器,但是不同的类型。
如果您使用 C 风格的字符串,只需使用 char
. 。如果您需要使用字符进行算术(非常罕见),请显式指定有符号或无符号以实现可移植性。
char
和 unsigned char
不保证在所有平台上都是 8 位类型 — 它们保证是 8 位或更大。部分平台有 9 位、32 位或 64 位字节. 。然而,当今最常见的平台(Windows、Mac、Linux x86 等)具有 8 位字节。
就直接值而言,当已知值介于两者之间时,将使用常规字符 CHAR_MIN
和 CHAR_MAX
而无符号字符在正端提供双倍的范围。例如,如果 CHAR_BIT
为8,常规范围 char
只保证为 [0, 127] (因为它可以有符号或无符号),而 unsigned char
将是 [0, 255] 并且 signed char
将是 [-127, 127]。
就其用途而言,标准允许 POD(普通旧数据)对象直接转换为无符号字符数组。这允许您检查对象的表示形式和位模式。对于 char 或signed char 来说,不存在相同的安全类型双关保证。
unsigned char
只接受正值......就像 0 到 255
然而
signed char
接受正值和负值......就像 -128 到 +127
unsigned char 是(无符号)字节值(0 到 255)。您可能会认为“char”是“字符”,但它实际上是一个数值。常规的“char”是有符号的,因此有 128 个值,并且这些值使用 ASCII 编码映射到字符。但无论哪种情况,您在内存中存储的都是字节值。
如果您喜欢使用各种类型的特定长度和符号,那么您可能最好使用 uint8_t、int8_t、uint16_t 等,因为它们完全按照它们所说的去做。
无符号字符使用为常规字符的符号保留的位作为另一个数字。这会将范围更改为 [0 - 255],而不是 [-128 - 127]。
通常,当您不需要符号时,会使用无符号字符。当执行诸如移位(移位扩展符号)之类的操作以及将 char 作为字节处理而不是将其用作数字时的其他操作时,这会产生影响。
unsigned char 是所有位欺骗的核心。在几乎所有平台的所有编译器中,无符号字符只是一个字节。(通常)8 位的无符号整数。可以将其视为一个小整数或一组位。
正如其他人所说,该标准没有定义 char 的符号。所以你有3种不同的“char”类型:字符、有符号字符、无符号字符。
一些谷歌搜索发现 这, ,人们对此进行了讨论。
无符号字符基本上是一个字节。因此,如果您需要一个字节的数据,您将使用它(例如,您可能想使用它来设置标志打开和关闭以传递给函数,就像 Windows API 中经常做的那样)。
引用自《C语言编程》一书:
预选赛 signed
或者 unsigned
可以应用于 char 或任何整数。未签名的数字始终为正或零,并遵守算术模量2^n的定律,其中n是类型中的位数。因此,例如,如果字符是8位,则未签名的char变量的值在0到255之间,而签名的字符的值在-128和127之间(在两台补充机器中)。是否签名或未签名是机器 - 依赖性但可打印的字符总是积极的。
unsigned char 只接受正值:0至255个签名的char需要正值和负值:-128 至 +127