【问题标题】:When would you use "signed char" over "unsigned char"?你什么时候会在“unsigned char”上使用“signed char”?
【发布时间】:2017-03-07 20:17:30
【问题描述】:

据我所知,unsigned charsigned char 之间没有太大区别,除了 -127 到 128 的有符号字符和 0 到 255 的无符号字符。我正在尝试学习 C++,我一直在想这个问题。另外,我很长一段时间都是 lua 程序员,所以我习惯于无符号字符,所以我只是想知道它们之间的区别以及什么时候你更愿意使用有符号字符而不是无符号字符。

谢谢。

【问题讨论】:

  • 如果你在做位操作,无符号类型是首选。
  • 请记住,如果普通char 被签名或没有签名,它的实现就被定义了。因此,如果您想要一个范围内的小整数,您可以使用signed char(或unsigned char)。但我宁愿推荐int8_tuint8_t 来代替(如果可用)用于通用小整数。
  • 哦,我明白了。感谢你们两位花时间回复
  • 有符号字符的范围通常在 -128 到 127 之间,因为补码会将“额外”值用于负数。在 C++11 之前,保证 范围仅为 -127 到 127,因为它允许 8 位符号幅度表示,即使大多数实现都是二进制补码。
  • unsigned char 是 C 的传统说法“字节”。 singed char 是一个小的有符号整数。一个应用程序是 3D 几何的迷你法线,其中 3 个浮点数会太占用内存。

标签: c++


【解决方案1】:

正如@SomeProgrammerDude 所解释的并且您已经知道,当您希望使用小的整数值时,您明确指定signedunsigned。在 AMD-64 架构上(这是 64 位通用 CPU 最广泛使用的架构,它可能是您笔记本电脑上的架构),signed char 占用 1 个字节,范围从 -128 到127,而unsigned char也占用1个字节,范围从0到255。

我想进一步推动这一点,展示使用signedunsigned 整数类型(例如charshortint,...)如何影响最终程序并且是实际执行。我将使用char的例子,但原理与其他整数类型相同。

假设我们有这个小程序:

// main.cpp

#include <iostream>

int main() {
    signed char   sc = (signed char)255; // equivalent to sc = -1
    unsigned char uc = 255;

    bool signedComp   = (sc <= 5);
    bool unsignedComp = (uc <= 5);

    return 0;
}

如果我们看一下汇编程序(代码与您的 CPU 实际执行的代码非常接近),我们可以观察到差异。这是汇编代码中最相关的部分:

movb    $-1, -4(%rbp) # sc = -1
movb    $-1, -3(%rbp) # uc = -1 (equivalent to uc = 255)

cmpb    $5, -4(%rbp)  # compare sc and 5, ...
setle   %al           # ... see whether sc was lower or equal (signed comparison), ...
movb    %al, -2(%rbp) # ... and set the boolean result into signedComp.

cmpb    $5, -3(%rbp)  # compare uc and 5, ...
setbe   %al           # ... see whether uc was below or equal (unsigned comparison), ...
movb    %al, -1(%rbp) # ... and set the boolean result into unsignedComp.

(如果您好奇并想自己生成汇编程序,请运行g++ -S main.cpp -o main.s -O0 并查看main.s 文件的一部分,您会在其中看到main: 标记。)

在您的内存中(特别是在堆栈上),scuc 都将占用 1 个字节。事实上,scuc 实际上包含255相同 值。然而,方式使得scuc 不同。

因此,这个:

unsigned charsigned char 之间没有太大区别

...具有讽刺意味的是 100% 正确。

从中吸取的教训是,程序员使用的数字只是概念性的。归根结底,关键在于如何使用 1 和 0。

【讨论】:

  • A signed char 必须至少覆盖从 -128 到 127 的范围,但它可以(有时更大)。同样,unsigned char 必须至少覆盖从 0 到 255 的范围,但它可以更大。因此,将 255 分配给 signed char 类型的变量的注释“相当于 sc = -1" 对于大多数系统来说可能是正确的,但这不是必需的,并且有些系统(具有较大的char 类型)不正确。
  • @PeteBecker «归根结底,关键在于如何处理 1 和 0。» QED。从而得到证明。
  • @PeteBecker 是的,有些平台并不等同,但答案明确表示它是针对“AMD-64 架构”的。对于您看到的大多数其他架构也是如此,例如 ARM。
  • @DanielH 我在@PeteBecker 的评论之后指定了“for AMD-64”。顺便说一句,我目前是一名 CS 工程专业的学生,​​在我们的第一年项目中,我们必须使用 avr-gcc 对 ATMega324PA 微控制器进行编程,这是一种用于微控制器的 gcc/g++ 调整。在这个编译器上(或者至少对于那个特定的微控制器),int 的大小是 2 个字节。但是,如果您正在制作无论如何都不适合不同架构的大型软件,我看不出使用unsigned char 而不是uint8_t 的缺点(尽管unsigned char 有点冗长)。我想这是一个习惯和观点的问题。
  • @martinkunev -- 不管 signed char 是如何表示的,语言定义都要求它能够表示从 -127 到 127 的所有整数值(我之前的评论错误地指出,较低的界是-128)。允许更大的范围。这有点难找,但它来自 SCHAR_MINSCHAR_MAX 的规范。
猜你喜欢
  • 2012-09-27
  • 2013-04-14
  • 2017-03-27
  • 2023-02-10
  • 1970-01-01
  • 2011-07-02
  • 2011-04-06
  • 1970-01-01
相关资源
最近更新 更多