有符号整数和无符号整数之间的区别是:
还有其他区别吗?
一般来说,这是正确的。在不知道你为什么要寻找差异的情况下,我想不出有符号和无符号之间的任何其他区别。
除了第二点,其他都是正确的。有符号整型有许多不同的表示法,有些实现使用第一种,有些使用最后一种,还有一些使用完全不同的表示法。这取决于你所使用的平台。
Unsigned值可以是一个较大的正数,而不能是负数。
是的。
Unsigned版本使用前导位作为值的一部分,而signed版本使用最左边的位来识别数字是正还是负。
有不同的表示有符号整数的方法。最容易可视化的是使用最左边的位作为标志(符号和幅度),但更常见的是二进制补码。这两种方法在大多数现代微处理器中都有使用——浮点数使用符号和幅度,而整数算术使用2的补数。
有符号整数可以同时包含正数和负数。
(回答第二个问题)通过只使用符号位(而不是2的补码),你可以得到-0。不太漂亮。
除此之外,在C语言中,你不能溢出一个无符号整数;行为被定义为模算术。您可以溢出一个有符号整数,并且在理论上(尽管在当前主流系统上没有实践),溢出可能会触发一个错误(可能类似于除零错误)。
为了完整起见,这里只提几点:
这个答案只讨论整数表示。浮点数可能有其他答案;
负数的表示可以有所不同。目前最常用的(到目前为止-今天几乎是通用的)是two's complement。其他表示包括one's complement(非常罕见)和符号幅度(非常罕见-可能只在博物馆藏品上使用),这只是简单地使用高位作为符号指示,其余位代表数字的绝对值。
当使用2的补数时,变量可以表示更大范围的负数(比正数多1)。这是因为0包含在“正数”中(因为符号位没有设置为0),而不包括负数。这意味着最小的负数的绝对值不能表示。
当使用某人的补数或有符号的幅度时,你可以将0表示为正数或负数(这是通常不使用这些表示的原因之一)。
我将在x86上讨论硬件层面的差异。除非您正在编写编译器或使用汇编语言,否则这几乎无关紧要。但很高兴知道。
首先,x86对有符号数字的二进制补码表示提供了本地的支持。您可以使用其他表示,但这将需要更多的指令,通常是浪费处理器时间。
我所说的“原生支持”是什么意思?我的意思是,有一组指令用于无符号数,另一组用于有符号数。无符号数可以与有符号数位于相同的寄存器中,实际上,您可以混合有符号和无符号指令,而不用担心处理器。由编译器(或汇编程序员)来跟踪数字是否带符号,并使用适当的指令。
首先,2的补数具有加减法与无符号数相同的性质。这些数字是正还是负没有区别。(所以你只要继续ADD和SUB你的数字就不用担心了。)
ADD
SUB
当进行比较时,差异开始显现出来。X86有一种简单的区分方法:上面/下面表示无符号比较,而大于/小于表示有符号比较。(例如JAE表示“如果高于或等于则跳跃”,并且是无符号的。)
JAE
还有两组乘除指令用于处理有符号整数和无符号整数。
最后:如果你想检查溢出,你可以对有符号数和无符号数做不同的检查。
C语言中有符号值和无符号值之间唯一的保证区别是有符号值可以为负、0或正,而无符号值只能为0或正。问题是C语言没有定义类型的格式(所以你不能知道你的整数是2的补码)。严格来说,你提到的前两点是不正确的。
无符号整数比有符号整数更容易让您陷入特定的陷阱。陷阱来自于当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
另一个区别是在不同大小的整数之间进行转换时。
例如,如果你从字节流中提取一个整数(简单来说就是16位),使用无符号值,你可以这样做:
i = ((int) b[j]) << 8 | b[j+1]
(可能应该强制转换2nd字节,但我猜编译器会做正确的事情)
对于有符号的值,你必须担心符号扩展,并做:
i = (((int) b[i]) & 0xFF) << 8 | ((int) b[i+1]) & 0xFF
在嵌入式系统上编程时,必须使用无符号整数。在循环中,当不需要有符号整数时,使用无符号整数将节省设计此类系统所需的安全。
有符号整数在C语言中表示数字。如果a和b是有符号整型变量,标准将永远不会要求编译器让表达式a+=b在a中存储除它们各自值的算术和以外的任何东西。可以肯定的是,如果算术和不适合a,处理器可能就不能把它放在那里,但标准不会要求编译器截断或换行值,或者在值超出其类型限制时做任何其他事情。注意,虽然标准不要求这样做,但C实现允许用带符号的值捕获算术溢出。
a
b
a+=b
C语言中的无符号整数表现为整数的抽象代数环,这些整数是2的某次幂的同余模,除非涉及到更大类型的转换或操作。将任何大小的整数转换为32位无符号类型将生成与该整数mod 4,294,967,296相等的成员。2减3得到4294967295的原因是,与3相等的数与与4294967295相等的数相加,会得到与2相等的数。
抽象代数环类型通常很方便;不幸的是,C使用符号作为类型是否应该表现为环的决定因素。更糟糕的是,当转换为更大的类型时,无符号值被视为数字而不是环成员,小于int的无符号值在对其执行任何算术时被转换为数字。如果v是一个等于4,294,967,294的uint32_t,那么v*=v;应该是v=4。不幸的是,如果int是64位,那么就不知道v*=v;能做什么。
int
v
4,294,967,294
uint32_t
v*=v;
v=4
鉴于标准的现状,我建议在需要与代数环相关的行为时使用无符号类型,在需要表示数字时使用有符号类型。不幸的是,C以这种方式进行了区分,但它们就是它们。
他只问了签过名和没签过名的。不知道为什么人们要在里面加额外的东西。让我来告诉你答案。
Unsigned:它只包含非负值,即0到255。
Signed:由正负值组成,但格式不同,如
这个解释是关于8位数字系统的。
根据我们在课堂上学到的,有符号整数可以表示正的而且负数,而无符号整数是只有非负的。
例如,查看一个8位数字:
无符号的值为0到255
0
255
签署的值从-128到127
-128
127
我找到的最好的答案是感谢IBM引用XDR标准:
整数 XDR有符号整数是一个编码的32位数据 范围为[-2147483648,2147483647]的整数。整数是 用二的补符号表示。最多和最少 有效字节分别为0和3。数据说明 Integers是整数 无符号整数 XDR无符号整数是一个32位的数据 对范围[0,4294967295]内的非负整数进行编码。它是 由无符号二进制数表示的,其最大值和最小值 有效字节分别为0和3。数据说明 无符号整数是无符号的
整数
XDR有符号整数是一个编码的32位数据 范围为[-2147483648,2147483647]的整数。整数是 用二的补符号表示。最多和最少 有效字节分别为0和3。数据说明 Integers是整数
无符号整数
XDR无符号整数是一个32位的数据 对范围[0,4294967295]内的非负整数进行编码。它是 由无符号二进制数表示的,其最大值和最小值 有效字节分别为0和3。数据说明 无符号整数是无符号的
参见维基百科上的XDR标准
这就是为什么我们用二进制来表示数字:一系列高电压(1)或低电压(0)的电子引脚。
但是,如果使用二进制计数,则只能表示自然数(0,1,2,…)。正好是2^n (n是比特数)个数。
如果您确保第一个操作数大于第二个操作数,则允许您执行加法、乘法、除法和减法,如果检查结果不超过您拥有的比特数,则结束。
然后,一些聪明的家伙来了,他们想:“当你用m >做n - m时会发生什么?”N,使用完全相同的算法?
...实际情况是这样的:你只需要在你的数字上加上1,如果你在后面有进位(环绕),然后考虑这两个都是0…0和1…1代表0。这是One的补码Ones' _补码 然而,这样做,你必须为符号保留一个位。从技术上讲,你可以表示-(2^(n-1)-1)≤n≤2^(n-1)-1的值 它们是:(2^n)-1(0的两种表示形式)。在这种表示形式中,你只需要交换所有的位来减去一个数字。
然后更聪明的家伙过来告诉我们:“如果我们认为当我们否定这个数字的时候总是有一个包裹呢?”...这意味着你在交换了比特之后再加一个。你得到2的补码 2的补码 使用它,你的0只有一个表示,你可以再次表示2^n个数字(2^(n-1)≤n≤2^(n-1)-1)。另外,a-b的计算实际上就是a+(-b),它只需要两种操作:add(a, add(swap(b), 1)))
a-b
a+(-b)
add(a, add(swap(b), 1)))
2补的另一个好处是,加法算法和无符号算法是一样的。因此,您将获得相同的属性,并使用相同的硬件来完成这两项任务。这就是为什么它是大多数计算机使用的表示法。
简而言之,有符号和无符号可以表示相同的数字计数,但在不同的范围内,现在,您可以准确地知道其中的原因了。有关所获得的代数结构的更多细节,请阅读此响应:https://stackoverflow.com/a/23304179/1745291
然后根据上下文使用其中一个(但是要注意,对于某些操作,如<,强制转换时的处理是不同的:((signed) -1) < 5但((unsigned) -1) > 5
<
((signed) -1) < 5
((unsigned) -1) > 5