C语言 C 如何在有符号和无符号整数中存储负数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26673013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does C store negative numbers in signed vs unsigned integers?
提问by A6SE
Here is the example:
这是示例:
#include <stdio.h>
int main()
{
int x=35;
int y=-35;
unsigned int z=35;
unsigned int p=-35;
signed int q=-35;
printf("Int(35d)=%d\n\
Int(-35d)=%d\n\
UInt(35u)=%u\n\
UInt(-35u)=%u\n\
UInt(-35d)=%d\n\
SInt(-35u)=%u\n",x,y,z,p,p,q);
return 0;
}
Output:
输出:
Int(35d)=35
Int(-35d)=-35
UInt(35u)=35
UInt(-35u)=4294967261
UInt(-35d)=-35
SInt(-35u)=4294967261
Does it really matter if I declare the value as signed or unsigned int? Because, C actually only cares about how I read the value from memory. Please help me understand this and I hope you prove me wrong.
如果我将值声明为有符号整数或无符号整数真的很重要吗?因为,C 实际上只关心我如何从内存中读取值。请帮助我理解这一点,我希望你证明我是错的。
回答by Jite
An unsigned intand a signed inttake up the same number of bytes in memory. They can store the same byte values. However the data will be treated differently depending on if it's signed or unsigned.
Anunsigned int和 asigned int在内存中占用的字节数相同。它们可以存储相同的字节值。但是,根据数据是有符号还是无符号,数据的处理方式会有所不同。
See http://en.wikipedia.org/wiki/Two%27s_complementfor an explanation of the most common way to represent integer values.
有关表示整数值的最常用方法的说明,请参阅http://en.wikipedia.org/wiki/Two%27s_complement。
Since you can typecast in C you can effectively force the compiler to treat an unsigned int as signed int and vice versa, but beware that it doesn't mean it will do what you think or that the representation will be correct. (Overflowing a signed integer invokes undefined behaviour in C).
由于您可以在 C 中进行类型转换,因此您可以有效地强制编译器将 unsigned int 视为有符号 int,反之亦然,但请注意,这并不意味着它会按照您的想法行事或表示将是正确的。(溢出有符号整数会调用 C 中的未定义行为)。
(As pointed out in comments, there are other ways to represent integers than two's complement, however two's complement is the most common way on desktop machines.)
(正如评论中所指出的,除了二进制补码之外,还有其他表示整数的方法,但是二进制补码是台式机上最常见的方式。)
回答by John Bode
Representation of signed integersis up to the underlying platform, not the C language itself. The language definition is mostly agnostic with regard to signed integer representations. Two's complementis probably the most common, but there are other representations such as one's complementand signed magnitude.
有符号整数的表示取决于底层平台,而不是 C 语言本身。关于有符号整数表示,语言定义大多是不可知的。 二进制补码可能是最常见的,但还有其他表示形式,例如一个补码和有符号幅度。
In a two's complement system, you negate a value by inverting the bits and adding 1. To get from 5to -5, you'd do:
在二补数系统,您可以通过翻转位和添加1.为了充分否定的值5来-5,你会怎么做:
5 == 0101 => 1010 + 1 == 1011 == -5
To go from -5back to 5, you follow the same procedure:
要从-5back 到5,请遵循相同的过程:
-5 == 1011 => 0100 + 1 == 0101 == 5
Does it really matter if I declare the value as signed or unsigned int?
如果我将值声明为有符号整数或无符号整数真的很重要吗?
Yes, for the following reasons:
是的,原因如下:
It affects the values you can represent: unsigned integers can represent values from
0to2N-1, whereas signed integers can represent values between-2N-1and2N-1-1(two's complement).Overflow is well-defined for unsigned integers;
UINT_MAX + 1will "wrap" back to0. Overflow is notwell-defined for signed integers, andINT_MAX + 1may"wrap" toINT_MIN, or it may not.Because of 1 and 2, it affects arithmetic results, especially if you mix signed and unsigned variables in the same expression (in which case the result may not be well defined if there's an overflow).
它会影响您可以表示的值:无符号整数可以表示从
0to 的值,而有符号整数可以表示介于和(二进制补码)之间的值。2N-1-2N-12N-1-1对于无符号整数,溢出是明确定义的;
UINT_MAX + 1将“包装”回0. 溢出对于有符号整数没有明确定义,INT_MAX + 1可能会“换行”到INT_MIN,也可能不会。由于 1 和 2,它会影响算术结果,特别是如果您在同一个表达式中混合使用有符号和无符号变量(在这种情况下,如果存在溢出,结果可能无法很好地定义)。
回答by glglgl
Does it really matter if I declare the value as signed or unsigned int?
如果我将值声明为有符号整数或无符号整数真的很重要吗?
Yes.
是的。
For example, have a look at
例如,看看
#include <stdio.h>
int main()
{
int a = -4;
int b = -3;
unsigned int c = -4;
unsigned int d = -3;
printf("%f\n%f\n%f\n%f\n", 1.0 * a/b, 1.0 * c/d, 1.0*a/d, 1.*c/b);
}
and its output
和它的输出
1.333333
1.000000
-0.000000
-1431655764.000000
which clearly shows that it makes a huge difference if I have the same byte representation interpreted as signed or unsigned.
这清楚地表明,如果我将相同的字节表示解释为有符号或无符号,则会产生巨大的差异。
回答by u4041521
#include <stdio.h>
int main(){
int x = 35, y = -35;
unsigned int z = 35, p = -35;
signed int q = -35;
printf("x=%d\tx=%u\ty=%d\ty=%u\tz=%d\tz=%u\tp=%d\tp=%u\tq=%d\tq=%u\t",x,x,y,y,z,z,p,p,q,q);
}
the result is: x=35 x=35 y=-35 y=4294967261 z=35 z=35 p=-35 p=4294967261 q=-35 q=4294967261
结果是: x=35 x=35 y=-35 y=4294967261 z=35 z=35 p=-35 p=4294967261 q=-35 q=4294967261
the int number store is not different, it stored with Complement style in memory,
int number store也一样,都是以Complement风格存储在内存中,
I can use 0X... the 35 in 0X00000023, and the -35 in 0Xffffffdd, it is not different you use sigend or unsigend. it only output with different sytle. The %d and %u is not different about positive, but the negative the first position is sign, if you output with %u is 0Xffffffdd equal 4294967261, but the %d the 0Xffffffdd can be - 0X00000023 equal -35.
我可以使用 0X... 0X00000023 中的 35,以及 0Xffffffdd 中的 -35,您使用 sigend 或 unsigend 没有什么不同。它只输出不同的风格。%d 和 %u 与正数没有区别,但负数第一个位置是符号,如果你用 %u 输出是 0Xffffffdd 等于 4294967261,但 %d 0Xffffffdd 可以是 - 0X00000023 等于 -35。
回答by Freddie Chopin
The most fundamental thing that variable's type defines is the way it is stored (that is - read from and written to) in memory and how are the bits interpreted, so your statement can be considered "valid".
变量类型定义的最基本的事情是它在内存中的存储方式(即 - 读取和写入)以及如何解释位,因此您的语句可以被视为“有效”。
You can also look at the problem using conversions. When you store signed and negative value in unsigned variable it gets converted to unsigned. It so happens that this conversion is reversible, so signed -35 converts to unsigned 4294967261, which - when you request it - can be converted to signed -35. That's how 2's complement encoding (see link in other answer) works.
您还可以使用转换来查看问题。当您在无符号变量中存储有符号和负值时,它会转换为无符号。碰巧这种转换是可逆的,因此有符号 -35 转换为无符号 4294967261,当您请求时,它可以转换为有符号 -35。这就是 2 的补码编码(参见其他答案中的链接)的工作原理。

![C语言 警告:多字符字符常量 [-Wmultichar]|](/res/img/loading.gif)