有符号与无符号整数

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

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

还有其他的区别?

  1. 是。

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

我将在x86上的硬件层面上进行分析。 除非你正在编写一个编译器或者使用汇编语言,否则这几乎是不相关的。 但很高兴知道。

首先,x86本身就支持有符号数的二进制补码表示。 您可以使用其他表示,但是这需要更多的指示,通常浪费处理器时间。

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

首先,二进制补码具有与无符号数加减相同的性质。 这些数字是正面的还是负面的都没有区别。 (所以你只要继续前进,不用担心就可以ADDSUB你的号码。)

当涉及到比较时,差异开始显现。 x86有一个区分它们的简单方法:上面/下面表示一个无符号比较,大于/小于表示有符号比较。 (例如, JAE意思是“如果高于或等于跳跃”,并且是无符号的。)

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

最后:如果你想检查溢出,你可以对签名和未签名的数字做不同的处理。

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

  1. 无符号:它只包含正值,即0到255。

  2. 签名:它包括正面和负面的价值观,但以不同的格式

    • -1到-128
    • 0到+127

这一切的解释是关于8位数字系统。

只是几点完整性:

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

  • 负数的表示可以变化。 今天使用的最普遍的(今天几乎是普遍的)是二的补充 。 其他表示包括补码 (相当less见)和有符号的幅度 (极less见 – 可能只用于博物馆作品),它仅仅使用高位作为符号指示符,剩下的位代表数字的绝对值。

  • 当使用二进制补码时,variables可以表示比正数大的负数范围(一个)。 这是因为零包含在“正”数字中(因为符号位不是零),而不是负数。 这意味着不能表示最小负数的绝对值。

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

除了第二点以外的所有内容都是正确 对于已签名的整数,有许多不同的符号,一些实现使用第一种,其他使用最后一种,而另一些则使用完全不同的一些。 这一切都取决于你正在使用的平台。

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

例如,看一个8位数字:

无符号0255

有符号的值范围从-128127

另一个区别是当你在不同大小的整数之间转换的时候。

例如,如果您要从字节stream中提取一个整数(比如16位,为了简单起见),使用无符号的值,您可以:

 i = ((int) b[j]) << 8 | b[j+1] 

(应该可以投2字节,但我猜编译器会做正确的事情)

使用带符号的值,您将不得不担心符号扩展,并执行:

 i = (((int) b[i]) & 0xFF) << 8 | ((int) b[i+1]) & 0xFF 

除了别人所说的,在C中,你不能溢出一个无符号整数; 行为被定义为模数算术。 你可以溢出一个有符号的整数,理论上(尽pipe在目前的主stream系统中并不实际),溢出可能会触发一个错误(可能类似于被零错误除法)。

(回答第二个问题)通过只使用一个符号位(而不是2的补码),您可以以-0结束。 不是很漂亮

一般来说这是正确的。 不知道更多关于为什么你正在寻找的差异,我想不出任何其他的签名和无符号之间的差异。

无符号整数比有符号整数更有可能捕捉到特定陷阱。 陷阱来自这样的事实,即上面的1和3是正确的,这两种types的整数可以被赋予一个超出它可以“保留”的范围的值,并且将被静静地转换。

 unsigned int ui = -1; signed int si = -1; if (ui < 0) { printf("unsigned < 0\n"); } if (si < 0) { printf("signed < 0\n"); } if (ui == si) { printf("%d == %d\n", ui, si); printf("%ud == %ud\n", ui, si); } 

当你运行这个,你会得到下面的输出,即使这两个值都被赋值为-1并且被声明为不同的值。

 signed < 0 -1 == -1 4294967295d == 4294967295d 
  1. 是的,无符号整数可以存储较大的值。
  2. 不,有不同的方式来显示正面和负面的价值。
  3. 是的,有符号整数可以包含正值和负值。

C中的整数代表数字。 如果ab是有符号整数types的variables,那么标准将永远不会要求编译器将expression式a+=b存储为除了它们各自值的算术和之外的任何东西。 可以肯定的是,如果算术和不适合a ,处理器可能无法放在那里,但是标准不需要编译器截断或者包装这个值,或者为了这个问题做任何其他的事情超出其types的限制。 请注意,虽然标准并不要求,但C实现允许使用带符号的值来捕获算术溢出。

C中的无符号整数performance为整数的抽象代数环,除了在涉及到转换或操作更大types的场景之外,它们是一致的。 将任意大小的整数转换为32位无符号types将会产生对应于与该整数mod 4,294,967,296一致的东西的成员。 从2中减去3的原因产生了4,294,967,295,即将与3相等的东西加到与4,294,967,295相同的东西将产生与2相等的东西。

抽象代数环types往往是方便的东西; 不幸的是,C使用符号作为决定一个types是否应该performance为环的因素。 更糟糕的是,无符号值在转换为较大types时被视为数字而不是环成员,并且在对它们执行任何算术运算时,小于int无符号值将被转换为数字。 如果v是等于4,294,967,294uint32_t ,则v*=v; 应该使v=4 。 不幸的是,如果int是64位,那么就不知道v*=v; 可以做。

鉴于这个标准,我build议在需要与代数环相关的行为的情况下使用无符号types,并且在想要表示数字时使用带符号types。 不幸的是C按照它的方式划分了区别,但是它们就是这样。

C中有符号和无符号值之间的唯一保证差异是有符号值可以是负值,0或正值,而无符号值只能是0或正值。 问题是C没有定义types的格式(所以你不知道你的整数是二进制补码)。 严格地说,你提到的前两点是不正确的。

在embedded式系统上编程时,您必须使用无符号整数。 在循环中,当不需要有符号整数时,使用无符号整数可以节省devise这些系统所需的安全性。