[英]understanding the behaviour of unsigned numbers
My goal is have a sorted ascending list of unsigned int values, I use the sub_func
to choose which one is greater. 我的目标是有一个unsigned int值的排序升序列表,我使用sub_func
来选择哪一个更大。
The sub_func
return is int
because I want to compare which one is greater for all the numbers it works fine but, I have a problem when I define the max value of unsigned int which is ( 0xffffffff == -1
). sub_func
返回是int
因为我想比较哪一个对于它工作正常的所有数字都更大但是,当我定义unsigned int的最大值( 0xffffffff == -1
)时,我遇到了问题。 I want to understand more on unsigned numbers over here. 我想更多地了解这里的无符号数字。 How would I solve this problem? 我该如何解决这个问题?
I have the following code: 我有以下代码:
#define p_max (0xffffffff)
uint32 a = p_max;
uint32 b = 20;
int sub_func(uint32 a, uint32 b)
{
return (b - a);
}
The retrun is 21, where as I want it to be 20 - MAX, which will be negative and my return type is negative. 后退是21,我希望它是20 - MAX,这将是负数,我的返回类型是负数。
But, i see it always a positive number. 但是,我认为它总是一个正数。 which I dont want, how to workaround this? 我不想要的,如何解决这个问题?
(Assuming uint32
is a 32 bit unsigned integral type). (假设uint32
是32位无符号整数类型)。
b - a
is an expression with type uint32
since both operands are of that type. b - a
是类型为uint32
的表达式,因为两个操作数都属于该类型。 Due to the standards-defined wrap-around behaviour of uint32
, it will have the value of 21. 由于uint32
的标准定义环绕行为,它的值为21。
You are assigning that to an int
type, hence the return value. 您将其分配给int
类型,因此返回值。
Don't mix int
and uint
unless it is really required as the max value is different because one bit will be used for sign. 除非确实需要,否则不要混用int
和uint
,因为最大值不同,因为一个位将用于符号。
Based on your latest comment, you can return 0 or 1 and then decide to add to tail/back or head/front. 根据您的最新评论,您可以返回0或1,然后决定添加到尾部/背部或头部/前部。
uint32 sub_func(uint32 a, uint32 b)
{
if( a > b )
return 0;
else
return 1;
}
You can also use bool data type if you want to return true or false. 如果要返回true或false,也可以使用bool数据类型。 Adjust your function return code based on the comparison and return data type. 根据比较和返回数据类型调整函数返回码。
Frist, signed
and unsigned
of same type are stored in same a space of same size (for example signed char
and unsigned char
are stored on 1 byte). 相同类型的Frist, signed
和unsigned
存储在相同大小的相同空间中(例如signed char
和unsigned char
存储在1个字节中)。 So, for signed
, half of possible values are used to store positive values and the other part of possible values are used to store negative values. 因此,对于有signed
,一半可能的值用于存储正值,另一部分可能的值用于存储负值。 For unsigned
, all possible values are for positive values only : 对于unsigned
,所有可能的值仅适用于正值:
signed char
: -127 to 127 signed char
:-127到127 unsigned char
: 0 to 255 unsigned char
:0到255 To calculate a negative, the most use solution is "two's complement". 要计算负数,最常用的解决方案是“二进制补码”。 To store -1 : 存储-1:
So, -1 is store in signed context as 255 in unsigned context. 因此,-1在无符号上下文中以有符号上下文存储为255。
It's for that every one say : don't mix signed and unsigned! 这是为了每个人都说: 不要混合签名和未签名!
Or if you really need that, use a greater size to calculate signed and be carefull : 或者,如果您确实需要,请使用更大的尺寸来计算签名并小心 :
std::uint32_t a;
std::uint32_t b;
std::int64_t = static_cast<std::int64_t>(b) - static_cast<std::int64_t>(a)
Example with 8 and 16 bits size data : http://coliru.stacked-crooked.com/a/38076c588de3907d 8位和16位大小数据的示例: http : //coliru.stacked-crooked.com/a/38076c588de3907d
What you are asking is impossible. 你问的是不可能的。
20 - 0xfffffff = -4294967275
which is not representable by an int, restricted to the range [-2147483648,2147483647]
. 不能用int表示,限制在[-2147483648,2147483647]
范围内。
The difference of two unsigned requires 33 bits ! 两个无符号的差异需要33位!
The fact you are storing the result in an int
does not prevent the subtraction being done using unsigned
arithmetic. 将结果存储在int
事实不会阻止使用unsigned
算术进行减法。
A subtraction of two uint32
always produces a result which is of type uint32
. 减去两个uint32
总是产生一个类型为uint32
的结果。 If the mathematical result of the subtraction is negative, modulo arithmetic is used to produce a value between 0
and the maximum that the unsigned type can represent. 如果减法的数学结果为负,则使用模运算产生介于0
和无符号类型可表示的最大值之间的值。
You have used that fact to get 0xFFFFFFFF
from -1
. 您已使用该事实从-1
获取0xFFFFFFFF
。 It works equally with results of subtraction. 它与减法结果同样有效。
20 - 0xfffffff
gives a value of -4294967275
. 20 - 0xfffffff
给出的值为-4294967275
。 That modulo 0x100000000
(the maximum a uint32
can represent, plus 1
) is 21
( 0x15
). 模数0x100000000
( uint32
可以表示的最大值加1
)为21
( 0x15
)。 21
converted to int
is still 21
. 21
转换为int
仍然是21
。
One way to produce a negative value is to avoid doing subtraction using unsigned
variables, such as; 产生负值的一种方法是避免使用unsigned
变量进行减法,例如;
int sub_func(uint32 a, uint32 b)
{
return (a > b) ? 1 : ((a < b) ? -1 : 0));
}
As the limit for a signed 32-bit int is [-2147483648,2147483647], it cannot hold the result of subtraction as it is out of the limit. 由于有符号的32位int的限制是[-2147483648,2147483647],因此它不能保持减法的结果,因为它超出了限制。 You can go for a 64-bit data type to hold the result of subtraction. 您可以使用64位数据类型来保存减法结果。 I tested the below code on Visual studio. 我在Visual Studio上测试了下面的代码。
#define p_max 0xffffffff
unsigned int a = p_max;
unsigned int b = 20;
signed long long sub_func()
{
return ((signed long long)b - (signed long long)a);
}
int main()
{
signed long long x = sub_func();
}
In the following code, the question is why the nResult would be 21 . 在下面的代码中,问题是为什么nResult将是21 。
#define p_max (0xffffffff)
uint32 a = p_max;
uint32 b = 20;
void main()
{
int nResult = b - a;
}
You are trying to calculate: 你试图计算:
0000 0000 0000 0000 0000 0000 0001 0100
- 1111 1111 1111 1111 1111 1111 1111 1111
0000 0000 0000 0000 0000 0000 0001 0100
- 1111 1111 1111 1111 1111 1111 1111 1111
which is actually computed as adding 实际上计算为添加
1
(2's complement of 1111 1111 1111 1111 1111 1111 1111 1111
) to 1
(2的补充1111 1111 1111 1111 1111 1111 1111 1111
)至
0000 0000 0000 0000 0000 0000 0001 0100
. 0000 0000 0000 0000 0000 0000 0001 0100
。
= 0000 0000 0000 0000 0000 0000 0001 0101
= 0000 0000 0000 0000 0000 0000 0001 0101
The result is 21 and there is no consideration of sign since it's produced by two uint32's operation. 结果是21并且没有考虑符号,因为它是由两个uint32的操作产生的。 So it doesn't make any change even if you cast the result value to signed int, because it's already a positive value. 因此,即使将结果值转换为signed int也不会进行任何更改,因为它已经是正值。
I just tested this with VC2013 and the compiler is treating the values as signed integers, hence getting 21! 我刚刚用VC2013对它进行了测试,编译器将值视为有符号整数,因此得到21! Here's the disembly:- 这是装备: -
int sub_func(uint32 a, uint32 b)
{
00B813C0 push ebp
00B813C1 mov ebp, esp
00B813C3 sub esp, 0C0h
00B813C9 push ebx
00B813CA push esi
00B813CB push edi
00B813CC lea edi, [ebp - 0C0h]
00B813D2 mov ecx, 30h
00B813D7 mov eax, 0CCCCCCCCh
00B813DC rep stos dword ptr es : [edi]
return (b - a);
00B813DE mov eax, dword ptr[b]
00B813E1 sub eax, dword ptr[a]
}
00B813E4 pop edi
00B813E5 pop esi
00B813E6 pop ebx
00B813E7 mov esp, ebp
00B813E9 pop ebp
00B813EA ret
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.