Answers:
无符号的可以具有较大的正值,而不能为负值。
是。
Unsigned使用前导位作为值的一部分,而signed版本使用最左边的位来标识数字是正数还是负数。
有多种表示有符号整数的方法。最简单的可视化方法是将最左边的位用作标志(符号和大小),但更常见的是二进制补码。两者都在大多数现代微处理器中使用-浮点使用符号和幅度,而整数算术使用二进制补码。
有符号整数可以同时包含正数和负数。
是
我将在x86的硬件级别上进行讨论。除非您正在编写编译器或使用汇编语言,否则这几乎是无关紧要的。但是很高兴知道。
首先,x86 对带符号的数字的二进制补码表示法具有原生支持。您可以使用其他表示形式,但这将需要更多说明,并且通常会浪费处理器时间。
“本地支持”是什么意思?基本上,我的意思是,有一组指令用于无符号数字,另一组用于签名数字。无符号数字可以与有符号数字位于相同的寄存器中,实际上您可以混合使用有符号和无符号指令,而不必担心处理器。由编译器(或汇编程序员)决定是否对数字签名,并使用适当的指令。
首先,二进制补码具有以下性质:加法和减法与无符号数相同。数字是正数还是负数都没有关系。(因此,您只需继续操作ADD
,SUB
您的电话号码便不用担心。)
在进行比较时,差异开始显示出来。x86有一种区分它们的简单方法:上方/下方表示无符号比较,大于/小于表示有符号比较。(例如,JAE
表示“如果等于或大于则跳转”,并且没有符号。)
还有两组乘法和除法指令,用于处理有符号和无符号整数。
最后:如果要检查(例如)溢出,则对带符号的和无符号的数字将做不同的处理。
他只询问已签名和未签名。不知道为什么人们会在其中添加额外的内容。让我告诉你答案。
无符号:它仅包含非负值,即0到255。
有符号:由负值和正值组成,但格式不同,例如
并且此说明是关于8位数字系统的。
完整性的几点说明:
这个答案只讨论整数表示。对于浮点数可能还有其他答案;
负数的表示形式可能有所不同。今天使用的最常见的(到目前为止-如今几乎是通用的)是二进制补码。其他表示形式包括补码(非常稀有)和带符号的幅度(极少出现-可能仅用于博物馆作品),其使用高位作为符号指示符,其余位表示数字的绝对值。
当使用二进制补码时,该变量可以表示比正数更大的负数范围(乘以一)。这是因为“正数”中包括零(因为未将符号位设置为零),而没有负数。这意味着不能表示最小负数的绝对值。
使用补码或带符号的幅度时,可以将零表示为正数或负数(这是通常不使用这些表示法的几个原因之一)。
除了第2点,其他所有内容都是正确的。有符号int有许多不同的表示法,有些实现使用第一个,另一些使用最后一个,而另一些使用完全不同的东西。这一切都取决于您使用的平台。
除了其他人所说的,在C语言中,您不能溢出一个无符号整数。该行为定义为模算术。您可以溢出一个有符号整数,并且从理论上讲(尽管实际上在当前主流系统上不是这样),该溢出可能会触发故障(也许类似于被零故障除以)。
(回答第二个问题)仅使用一个符号位(而不是2的补码),就可以得到-0。不太漂亮
C中的带符号整数表示数字。如果a
和b
是带符号整数类型的变量,则该标准绝不需要编译器将表达式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
是uint32_t
等于4,294,967,294
,那么v*=v;
应该做v=4
。不幸的是,如果int
是64位,则无法确定该v*=v;
怎么做。
给定目前的标准,我建议在需要与代数环相关的行为的情况下使用无符号类型,而在要表示数字时使用有符号类型。不幸的是,C像以前那样区分了它们,但它们就是它们。
与有符号整数相比,无符号整数更容易在特定陷阱中吸引您。陷阱来自以下事实:虽然上面的1和3是正确的,但是可以为两种类型的整数分配一个超出其“保持”范围的值,并且将对其进行静默转换。
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