我的目标是有一个unsigned int值的排序升序列表,我使用sub_func
来选择哪一个更大。
sub_func
返回int
,因为我想比较哪一个对于它工作正常的所有数字都更大但是,当我定义unsigned int的最大值时,我有一个问题是( 0xffffffff == -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 - MAX,这将是负数,我的返回类型是负数。
但是,我认为它总是一个正数。我不想要的,如何解决这个问题?
答案 0 :(得分:5)
(假设uint32
是32位无符号整数类型)。
b - a
是一个类型为uint32
的表达式,因为两个操作数都属于该类型。由于uint32
的标准定义环绕行为,它的值为21。
您将其分配给int
类型,因此返回值。
答案 1 :(得分:2)
不要混用int
和uint
,除非确实需要,因为最大值不同,因为一位将用于签名。
根据您的最新评论,您可以返回0或1,然后决定添加到尾部/背部或头部/前部。
uint32 sub_func(uint32 a, uint32 b)
{
if( a > b )
return 0;
else
return 1;
}
如果要返回true或false,也可以使用bool数据类型。根据比较和返回数据类型调整函数返回码。
答案 2 :(得分:1)
相同类型的Frist,signed
和unsigned
存储在相同大小的相同空间中(例如signed char
和unsigned char
存储在1个字节上)。因此,对于signed
,一半可能的值用于存储正值,另一部分可能的值用于存储负值。对于unsigned
,所有可能的值仅适用于正值:
signed char
: - 127到127 unsigned char
:0到255 要计算负数,最常用的解决方案是"两个补码"。存储-1:
因此,-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)
8位和16位大小数据的示例:http://coliru.stacked-crooked.com/a/38076c588de3907d
答案 3 :(得分:1)
你所要求的是不可能的。
20 - 0xfffffff = -4294967275
,无法用int表示,仅限于范围[-2147483648,2147483647]
。
两个无符号的差异需要33位!
答案 4 :(得分:1)
您将结果存储在int
中这一事实并不妨碍使用unsigned
算法完成减法。
减去两个uint32
总会产生uint32
类型的结果。如果减法的数学结果为负,则使用模运算产生0
与无符号类型可表示的最大值之间的值。
您已使用该事实从0xFFFFFFFF
获取-1
。它与减法结果同样有效。
20 - 0xfffffff
的值为-4294967275
。该模0x100000000
(uint32
可以表示的最大值加上1
)是21
(0x15
)。转换为21
的{{1}}仍为int
。
产生负值的一种方法是避免使用21
变量进行减法,例如;
unsigned
答案 5 :(得分:0)
由于有符号的32位int的限制是[-2147483648,2147483647],因此它不能保持减法的结果,因为它超出了限制。您可以使用64位数据类型来保存减法结果。我在Visual studio上测试了下面的代码。
$myusername = "myusername";
$mypassword = "mypassword";
$site_url = "https:// my site url";
$cookiefile = "cookie_filename.txt";
$uagent = "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US....;
$postDatas = 'username='.$myusername.'&password='.$mypassword;
//----------1st request start---------
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$site_url);
curl_setopt($ch, CURLOPT_USERAGENT, $uagent);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postDatas);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
$res = curl_exec($ch);
curl_close ($ch);
//----------1st request end---------
//----------2nd request start---------
$meee = explode("jsessionid=",str_replace("Content-Length:","",$res));
$sessId = explode(" ",trim($meee[1]));
$postDatas2 = $postDatas.'&jsessionid='.trim($sessId[0]);
$headers_curl = array(
"Accept-Encoding: .....",
"Accept-Language: .....",
"Accept: .....",
"Set-Cookie: SESSIONIDS=".trim($sessId[0])."",
"Path=....",
"Cache-Control: max-age=0",
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https:// my 2nd url");
curl_setopt($ch, CURLOPT_USERAGENT, $uagent);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postDatas2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiefile);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers_curl);
curl_setopt($ch, CURLOPT_REFERER, "https://my refer url");
curl_exec($ch);
//----------2nd request end--------
//----------3rd request start---------
curl_setopt($ch, CURLOPT_URL,"https:// my 3rd url");
curl_setopt($ch, CURLOPT_USERAGENT, $uagent);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postDatas2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiefile);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers_curl);
curl_setopt($ch, CURLOPT_REFERER, "https://......");
$checkResult = curl_exec($ch);
//----------3rd request end---------
preg_match_all('/<td width.*value="(.*)<\/form>/s',$checkResult,$chkData3);
preg_match_all('/value=.*?(.*)|">/',$chkData3[0][0],$checkKey);
$checkKey[1] =
preg_replace('/[^a-zA-Z0-9_ %\[\]\.\(\)%&-]/s', '', $checkKey[1]);
//--------------end--------------------
答案 6 :(得分:0)
在以下代码中,问题是为什么 nResult 21 。
#define p_max (0xffffffff)
uint32 a = p_max;
uint32 b = 20;
void main()
{
int nResult = b - a;
}
您正在尝试计算:
0000 0000 0000 0000 0000 0000 0001 0100
- 1111 1111 1111 1111 1111 1111 1111 1111
实际上计算为添加
1
(1111 1111 1111 1111 1111 1111 1111 1111
的2'补码)
0000 0000 0000 0000 0000 0000 0001 0100
。
= 0000 0000 0000 0000 0000 0000 0001 0101
结果是21并且没有考虑符号,因为它是由两个uint32的操作产生的。因此即使将结果值转换为signed int也不会进行任何更改,因为它已经是正值。
答案 7 :(得分:-1)
我刚用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