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

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

还有其他区别吗?


当前回答

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以这种方式进行了区分,但它们就是它们。

其他回答

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

无符号整数比有符号整数更容易让您陷入特定的陷阱。陷阱来自于这样一个事实:虽然上面的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

关于这个问题,我找到的最佳答案要感谢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标准

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

例如,如果你从字节流中提取一个整数(简单来说就是16位),使用无符号值,你可以这样做:

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

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

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

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

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

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

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