繁体   English   中英

什么是无符号字符?

[英]What is an unsigned char?

在 C/C++ 中, unsigned char有什么用? 它与普通的char有何不同?

在 C++ 中,存在三种不同的字符类型:

  • char
  • signed char
  • unsigned char

如果您对text使用字符类型,请使用不合格的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的符号。 根据平台的不同, char 可能是signedunsigned ,因此如果您的实现依赖于它,您需要明确要求signed charunsigned char 如果您打算表示字符串中的字符,只需使用char ,因为这将匹配您的平台放入字符串中的内容。

signed charunsigned char之间的区别正如您所期望的。 在大多数平台上, signed char将是一个 8 位二进制补码,范围从-128127 ,而unsigned char将是一个 8 位无符号整数( 0255 )。 注意标准不要求char类型有 8 位,只有sizeof(char)返回1 您可以在limits.h使用CHAR_BIT获取字符中的位数。 不过,今天几乎没有平台会是8以外的平台。

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

正如其他人在我发布这篇文章后提到的int8_t ,如果您真的想表示小整数,最好使用int8_tuint8_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?

  1. 所有位都参与确定其值——也就是说,对象中不出现填充位。
  2. 仅将一次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] 范围内,因此这些值通常被解释为:

  • 0 表示完全没有给定的颜色成分。
  • 255 表示 100% 的给定颜色颜料。

所以你最终会得到 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_tuint8_t类型。

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

然而

signed char采用正值和负值......比如-128+127

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

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

如果您使用 C 风格的字符串,只需使用char 如果您需要将字符用于算术(很少见),请明确指定有符号或无符号以实现可移植性。

charunsigned char不能保证在所有平台上都是 8 位类型——它们保证是 8 位或更大。 某些平台具有9 位、32 位或 64 位字节 但是,当今最常见的平台(Windows、Mac、Linux x86 等)具有 8 位字节。

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

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

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

如果您喜欢使用各种类型的特定长度和符号,那么使用uint8_tint8_tuint16_t等可能会更好,因为它们完全按照他们所说的去做。

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

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

unsigned char只取正值:0 到 255,而signed char取正值和负值:-128 到 +127。

一些谷歌搜索发现了这个,人们对此进行了讨论。

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

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

当您不需要符号时,通常使用无符号字符。 在将 char 作为字节处理而不是将其用作数字时,这将在执行诸如移位(移位扩展符号)之类的操作和其他操作时有所不同。

引用自《c 编程语言》一书:

限定符有signedunsigned可应用于 char 或任何整数。 无符号数总是正数或零,并遵守算术模 2^n 的法则,其中 n 是类型中的位数。 因此,例如,如果字符是 8 位,则无符号字符变量的值介于 0 和 255 之间,而有符号字符的值介于 -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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM