C++ 理解无符号数的行为
我的目标是有一个无符号int值的有序升序列表,我使用C++ 理解无符号数的行为,c++,c,unsigned,C++,C,Unsigned,我的目标是有一个无符号int值的有序升序列表,我使用sub_func选择哪个更大 sub_func返回值是int,因为我想比较所有数字中哪一个更大,它可以正常工作,但是,当我定义无符号int的最大值(0xffffff==-1)时,我遇到了一个问题。我想了解更多关于无符号数字的信息。我该如何解决这个问题 我有以下代码: #define p_max (0xffffffff) uint32 a = p_max; uint32 b = 20; int sub_func(uint32 a, uint32
sub_func
选择哪个更大
sub_func
返回值是int
,因为我想比较所有数字中哪一个更大,它可以正常工作,但是,当我定义无符号int的最大值(0xffffff==-1
)时,我遇到了一个问题。我想了解更多关于无符号数字的信息。我该如何解决这个问题
我有以下代码:
#define p_max (0xffffffff)
uint32 a = p_max;
uint32 b = 20;
int sub_func(uint32 a, uint32 b)
{
return (b - a);
}
retrun是21,我希望它最大值是20,它是负数,我的返回类型是负数
但是,我总是看到一个正数。我不想看到的是,如何解决这个问题?不要将
int
和uint
混合使用,除非确实需要,因为最大值不同,因为符号将使用一位
根据您最近的评论,您可以返回0或1,然后决定添加到tail/back或head/front
uint32 sub_func(uint32 a, uint32 b)
{
if( a > b )
return 0;
else
return 1;
}
如果要返回true或false,也可以使用bool数据类型。根据比较和返回数据类型调整函数返回代码。(假设uint32
为32位无符号整数类型)
b-a
是类型为uint32
的表达式,因为两个操作数都属于该类型。由于标准定义了uint32
的环绕行为,其值为21
您正在将其分配给一个
int
类型,因此返回值。第一,相同类型的有符号的和无符号的存储在相同大小的相同空间中(例如有符号的字符和无符号的字符存储在1字节上)。因此,对于有符号的
,一半可能值用于存储正值,另一部分可能值用于存储负值。对于无符号
,所有可能的值仅适用于正值:
签名字符
:-127到127
无符号字符
:0到255
要计算负数,最常用的方法是“两个补”。要存储-1:
- 使用值1:0x01
- 反转它:0xFE
- 添加1:0xFF
因此,-1在有符号上下文中存储为255在无符号上下文中存储
每个人都会说:不要把有符号和无符号混为一谈强>
或者,如果您确实需要,请使用更大的大小来计算签名,并且要小心:
std::uint32_t a;
std::uint32_t b;
std::int64_t = static_cast<std::int64_t>(b) - static_cast<std::int64_t>(a)
std::uint32\u t a;
标准:uint32_t b;
std::int64\u t=静态强制转换(b)-静态强制转换(a)
8位和16位大小数据的示例:您所要求的是不可能的
20 - 0xfffffff = -4294967275
不可由int表示,仅限于范围[-21474836482147483647]
两个无符号的差需要33位 我刚刚用VC2013测试了这一点,编译器将这些值视为有符号整数,因此得到了21!这是拆解:-
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
由于有符号32位整数的限制为[-21474836482147483647],它无法保存减法结果,因为它超出了限制。您可以选择64位数据类型来保存减法结果。我在VisualStudio上测试了以下代码
#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();
}
将结果存储在int
中并不妨碍使用无符号
算法进行减法运算
减去两个uint32
始终会生成类型为uint32
的结果。如果减法的数学结果为负,则使用模运算产生一个介于0
和无符号类型可以表示的最大值之间的值
您已使用该事实从-1
获取0xFFFFFFFF
。它与减法的结果一样有效
20-0xfffffff
给出的值为-4294967275
。模0x100000000
(auint32
可以表示的最大值,加上1
)是21
(0x15
)<代码>21
转换为int
仍然是21
产生负值的一种方法是避免使用无符号
变量进行减法,例如
int sub_func(uint32 a, uint32 b)
{
return (a > b) ? 1 : ((a < b) ? -1 : 0));
}
int sub_func(uint32 a,uint32 b)
{
返回值(a>b)?1:((a
在下面的代码中,问题是为什么nResult会是21
#define p_max (0xffffffff)
uint32 a = p_max;
uint32 b = 20;
void main()
{
int nResult = b - a;
}
您正在尝试计算:
0000 0000 0000 0001 0100
-1111111111111111111111111111111111111111111111111
这实际上被计算为加法
1
(2的1111111111111111111111111111111111111111
)到
0000 0000 0001 0100
=0000 0000 0001 0101
结果是21,不考虑符号,因为它是由两个uint32操作生成的。因此,即使您将结果值强制转换为带符号的int,它也不会做出任何更改,因为它已经是一个正值。如果a和false
,为什么不使用标准方法返回true
?想想当a=b=max
时的情况,您需要一个更宽的有符号类型,例如C++11的long
,它至少是64位。我想要返回值,这对我的进一步编码很重要。无符号
值不能为负。嗯,当这两个值之间的差值大于0x7fffffff
时,您的计划是什么?您确定需要有符号的差值吗?你的+/-或+1/0/-1不够吗?你的无符号字符和有符号字符不是颠倒过来了吗?另外,在C++14之前,有符号字符可以从-127到+127。所以,如果我将p_max声明为0x0fffffff,这会起作用吗?@invicur这是一个解决方案是的,将无符号
限制为有符号
的最大值