有符号整数和无符号整数之间的区别是:

Unsigned值可以是一个较大的正数,而不能是负数。 Unsigned版本使用前导位作为值的一部分,而signed版本使用最左边的位来识别数字是正还是负。 有符号整数可以同时包含正数和负数。

还有其他区别吗?


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


除了第二点,其他都是正确的。有符号整型有许多不同的表示法,有些实现使用第一种,有些使用最后一种,还有一些使用完全不同的表示法。这取决于你所使用的平台。


Unsigned值可以是一个较大的正数,而不能是负数。

Yes.

Unsigned版本使用前导位作为值的一部分,而signed版本使用最左边的位来识别数字是正还是负。

有不同的表示有符号整数的方法。最容易想象的是使用最左边的位作为标志(符号和幅度),但更常见的是2的补位。这两种方法在大多数现代微处理器中都有使用——浮点数使用符号和幅度,而整数算术使用2的补数。

有符号整数可以同时包含正数和负数。

Yes.


(回答第二个问题)通过只使用符号位(而不是2的补码),你可以得到-0。不太漂亮。


除此之外,在C语言中,你不能溢出一个无符号整数;行为被定义为模算术。您可以溢出一个有符号整数,并且在理论上(尽管在当前主流系统上没有实践),溢出可能会触发一个错误(可能类似于除零错误)。


为了完整起见,这里只提几点:

this answer is discussing only integer representations. There may be other answers for floating point; the representation of a negative number can vary. The most common (by far - it's nearly universal today) in use today is two's complement. Other representations include one's complement (quite rare) and signed magnitude (vanishingly rare - probably only used on museum pieces) which is simply using the high bit as a sign indicator with the remain bits representing the absolute value of the number. When using two's complement, the variable can represent a larger range (by one) of negative numbers than positive numbers. This is because zero is included in the 'positive' numbers (since the sign bit is not set for zero), but not the negative numbers. This means that the absolute value of the smallest negative number cannot be represented. when using one's complement or signed magnitude you can have zero represented as either a positive or negative number (which is one of a couple of reasons these representations aren't typically used).


我将在x86上讨论硬件层面的差异。除非您正在编写编译器或使用汇编语言,否则这几乎无关紧要。但很高兴知道。

首先,x86原生支持这两个数字的有符号数的补表示。您可以使用其他表示,但这将需要更多的指令,通常是浪费处理器时间。

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

首先,2的补数具有加减法与无符号数相同的性质。这些数字是正还是负没有区别。(所以你只要继续做加法和减法就可以了,不用担心。)

当进行比较时,差异开始显现出来。X86有一种简单的区分方法:上面/下面表示无符号比较,而大于/小于表示有符号比较。(例如,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]

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

对于有符号的值,你必须担心符号扩展,并做:

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

是的,无符号整数可以存储大的值。 不,有不同的方式来表示正数和负数。 是的,有符号整数可以包含正数和负数。


在嵌入式系统上编程时,必须使用无符号整数。在循环中,当不需要有符号整数时,使用无符号整数将节省设计此类系统所需的安全。


Signed integers in C represent numbers. If a and b are variables of signed integer types, the standard will never require that a compiler make the expression a+=b store into a anything other than the arithmetic sum of their respective values. To be sure, if the arithmetic sum would not fit into a, the processor might not be able to put it there, but the standard would not require the compiler to truncate or wrap the value, or do anything else for that matter if values that exceed the limits for their types. Note that while the standard does not require it, C implementations are allowed to trap arithmetic overflows with signed values.

Unsigned integers in C behave as abstract algebraic rings of integers which are congruent modulo some power of two, except in scenarios involving conversions to, or operations with, larger types. Converting an integer of any size to a 32-bit unsigned type will yield the member corresponding to things which are congruent to that integer mod 4,294,967,296. The reason subtracting 3 from 2 yields 4,294,967,295 is that adding something congruent to 3 to something congruent to 4,294,967,295 will yield something congruent to 2.

Abstract algebraic rings types are often handy things to have; unfortunately, C uses signedness as the deciding factor for whether a type should behave as a ring. Worse, unsigned values are treated as numbers rather than ring members when converted to larger types, and unsigned values smaller than int get converted to numbers when any arithmetic is performed upon them. If v is a uint32_t which equals 4,294,967,294, then v*=v; should make v=4. Unfortunately, if int is 64 bits, then there's no telling what v*=v; could do.

鉴于标准的现状,我建议在需要与代数环相关的行为时使用无符号类型,在需要表示数字时使用有符号类型。不幸的是,C以这种方式进行了区分,但它们就是它们。


他只问了签过名和没签过名的。不知道为什么人们要在里面加额外的东西。让我来告诉你答案。

Unsigned:它只包含非负值,即0到255。 Signed:由正负值组成,但格式不同,如 0 ~ +127 -1 ~ -128

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


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

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

无符号值为0到255

带符号的取值范围为-128 ~ 127


关于这个问题,我找到的最佳答案要感谢IBM引用的XDR标准:

Integer An XDR signed integer is a 32-bit piece of data that encodes an integer in the range [-2147483648,2147483647]. The integer is represented in two's complement notation. The most and least significant bytes are 0 and 3, respectively. The data description of integers is integer. Unsigned integer An XDR unsigned integer is a 32-bit piece of data that encodes a nonnegative integer in the range [0,4294967295]. It is represented by an unsigned binary number whose most and least significant bytes are 0 and 3, respectively. The data description of unsigned integers is unsigned.

参见维基百科上的XDR标准


这都是关于建模的: 当您想要设计一台计算机时,您需要采用约定来表示数据以及如何计算它们。当然,为不同的模型提供不同的操作和属性(性能、所需的内存空间、硬件实现复杂性等)。

事实证明,通过基于电学(因此是电子学)的计算,我们发现表示信息的最方便的方法是使用电压级别. ...计算这些电压水平最方便的方法是考虑两种状态:有电压和没有电压。 “bit”来了。

这就是为什么我们用二进制来表示数字:一系列高电压(1)或低电压(0)的电子引脚。

但是,如果使用二进制计数,则只能表示自然数(0,1,2,…)。正好是2^n (n是比特数)个数。

如果您确保第一个操作数大于第二个操作数,则允许您执行加法、乘法、除法和减法,如果检查结果不超过您拥有的比特数,则结束。

然后,一些聪明的家伙过来问:“当你用m >n做n - m时会发生什么,使用完全相同的算法?”

...实际情况是这样的:你只需要在你的数字上加上1,如果你在后面有进位(环绕),然后考虑这两个都是0…0和1…1代表0。这是1的补1的_complement 然而,这样做,你必须为符号保留一个位。从技术上讲,你可以表示-(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)))

2补的另一个好处是,加法算法和无符号算法是一样的。因此,您将获得相同的属性,并使用相同的硬件来完成这两项任务。这就是为什么它是大多数计算机使用的表示法。

简而言之,有符号和无符号可以表示相同的数字计数,但在不同的范围内,现在,您可以准确地知道其中的原因了。有关获得的代数结构的更多详细信息,请阅读此响应:https://stackoverflow.com/a/23304179/1745291

然后根据上下文使用一个或另一个(注意,对于某些操作,如<,强制转换时的处理是不同的:((signed) -1) < 5但((unsigned) -1) > 5