签名与无符号整数

378 language-agnostic unsigned signed integer

我是否正确地说有符号和无符号整数之间的区别是:

  1. 无符号可以保持较大的正值,而不是负值.
  2. 无符号使用前导位作为值的一部分,而带符号版本使用最左侧位来标识数字是正数还是负数.
  3. 有符号整数可以包含正数和负数.

还有其他差异吗?

Gre*_*reg 332

无符号可以保持较大的正值,而不是负值.

是.

无符号使用前导位作为值的一部分,而带符号版本使用最左侧位来标识数字是正数还是负数.

表示有符号整数的方法有很多种.最容易想象的是使用最左边的位作为标志(符号和幅度),但更常见的是两个补码.两者都在大多数现代微处理器中使用 - 浮点使用符号和幅度,而整数运算使用二进制补码.

有符号整数可以包含正数和负数.

  • @Greg链接坏了 (8认同)

Art*_*ius 89

我将在x86上的硬件级别上进行分析.除非您正在编写编译器或使用汇编语言,否则这几乎无关紧要.但很高兴知道.

首先,X86具有原生的支持二进制补码符号数的表示.您可以使用其他表示形式,但这需要更多指令,通常会浪费处理器时间.

"原生支持"是什么意思?基本上我的意思是你有一组用于无符号数字的指令和另一套用于有符号数字的指令.无符号数字可以与有符号数字位于相同的寄存器中,实际上,您可以混合有符号和无符号指令,而无需担心处理器.由编译器(或汇编程序员)来跟踪数字是否已签名,并使用适当的指令.

首先,二进制补码数具有加法和减法与无符号数相同的特性.数字是正数还是负数没有区别.(所以你只需要继续,ADD并且SUB不用担心你的数字.)

在进行比较时,差异开始显现.x86有一种区分它们的简单方法:上/下表示无符号比较,大于/小于表示已签名比较.(例如,JAE"如果大于或等于跳跃"并且是未签名的.)

还有两组乘法和除法指令来处理有符号和无符号整数.

最后:如果你想检查溢出,你会对签名和无符号数做不同的处理.


小智 59

基本上他只询问签名和未签名.不知道为什么人们会在这里添加额外的东西.我来告诉你答案.

  1. 无符号:仅包含正值,即0到255.

  2. 签名:它包含负值和正值,但有不同的格式,如

    • -1到-128
    • 0到+127

这一切都是关于8位数系统的解释.

  • 好的。简单的。简洁的。很棒的工作。 (2认同)

Mic*_*urr 15

完整性只需几点:

  • 这个答案只讨论整数表示.浮点可能还有其他答案;

  • 负数的表示可以变化.今天使用的最常见的(到目前为止 - 它几乎是通用的)是两个补充.其他表示包括一个补码(非常罕见)和有符号的幅度(很少见 - 可能仅用于博物馆作品),它只是使用高位作为符号指示符,其余位代表数字的绝对值.

  • 当使用二进制补码时,变量可以表示比正数更大的负数范围(乘以1).这是因为"正"数字中包含零(因为符号位未设置为零),而不是负数.这意味着无法表示最小负数的绝对值.

  • 当使用一个补码或有符号幅度时,您可以将零表示为正数或负数(这是通常不使用这些表示的几个原因之一).


小智 13

根据我们在课堂上学到的东西,有符号整数可以表示正数负数,而无符号整数只是非负数.

例如,查看一个8位数字:

无符号0255

签署值的范围从-128127


Jas*_*ers 11

除第2点以外的所有内容都是正确的.签名整数有许多不同的符号,一些实现使用第一个,其他实现使用最后一个,而其他实现使用完全不同的东西.这一切都取决于您正在使用的平台.


Mik*_*een 10

另一个区别是当您在不同大小的整数之间进行转换时.

例如,如果要从字节流中提取整数(为简单起见,则为16位),使用无符号值,您可以执行以下操作:

i = ((int) b[j]) << 8 | b[j+1]
Run Code Online (Sandbox Code Playgroud)

(应该可能会转换第二个字节,但我猜测编译器会做正确的事情)

使用签名值,您将不得不担心签名扩展并执行:

i = (((int) b[i]) & 0xFF) << 8 | ((int) b[i+1]) & 0xFF
Run Code Online (Sandbox Code Playgroud)


Jon*_*ler 6

除了其他人所说的,在 C 中,您不能溢出无符号整数;该行为被定义为模数算术。您可以溢出一个有符号整数,理论上(尽管在当前主流系统上没有实践),溢出可能会触发故障(可能类似于除以零故障)。

  • 请注意,有符号整数溢出确实会触发未定义的行为,现代编译器非常积极地发现这一点并利用它以意想不到但技术上合法的方式修改您的程序,因为它们被允许假设未定义的行为不会发生 - 粗略地说。与 7 年前相比,这现在是一个更大的问题。 (2认同)

sup*_*cat 6

C 中的有符号整数表示数字。如果ab是有符号整数类型的变量,则标准永远不会要求编译器将表达式a+=b存储为a除各自值的算术和之外的任何内容。可以肯定的是,如果算术和不适合a,处理器可能无法将其放在那里,但标准不会要求编译器截断或包装该值,或者在值超过时执行任何其他操作它们的类型的限制。请注意,虽然标准没有要求,但 C 实现允许使用有符号值捕获算术溢出。

C 中的无符号整数表现为整数的抽象代数环,它们以 2 的某个幂为模全等,但涉及到较大类型的转换或运算的情况除外。将任意大小的整数转换为 32 位无符号类型将产生与该整数 mod 4,294,967,296 全等的内容对应的成员。2 减去 3 得到 4,294,967,295 的原因是,将与 3 全等的东西加到与 4,294,967,295 全等的东西上会得到与 2 全等的东西。

抽象代数环类型通常是很方便的东西;不幸的是,C 使用符号性作为类型是否应表现为环的决定因素。更糟糕的是,当转换为较大类型时,无符号值被视为数字而不是环成员,而小于的无符号值int在对其执行任何算术时会被转换为数字。如果v是 auint32_t等于4,294,967,294,那么v*=v;应该使v=4。不幸的是,如果int是 64 位,那么不知道v*=v;能做什么。

鉴于目前的标准,我建议在需要与代数环相关的行为的情况下使用无符号类型,而在想要表示数字时使用有符号类型。不幸的是,C 按照它的方式进行了区分,但它们就是这样。


tod*_*ddk 5

一般来说,这是正确的。在不知道您为什么要寻找差异的更多信息的情况下,我想不出有符号和无符号之间的任何其他区别。


Rya*_*yer 5

(回答第二个问题)仅使用符号位(而不是 2 的补码),最终结果可能是 -0。不太漂亮。