我看到了以下代码(函数的一部分):
if (end == start)
{
*max = *min = *start;
return 0x80000000;
}
我不明白为什么它返回0x80000000,即2^31
,并且它超出了int的范围并且类型为unsigned int
它等于什么?
完整代码:
int MaxDiffCore(int* start, int* end, int* max, int* min)
{
if (end == start)
{
*max = *min = *start;
return 0x80000000;
}
int* middle = start + (end - start) / 2;
int maxLeft, minLeft;
int leftDiff = MaxDiffCore(start, middle, &maxLeft, &minLeft);
int maxRight, minRight;
int rightDiff = MaxDiffCore(middle + 1, end, &maxRight, &minRight);
int crossDiff = maxLeft - minRight;
*max = (maxLeft > maxRight) ? maxLeft : maxRight;
*min = (minLeft < minRight) ? minLeft : minRight;
int maxDiff = (leftDiff > rightDiff) ? leftDiff : rightDiff;
maxDiff = (maxDiff > crossDiff) ? maxDiff : crossDiff;
return maxDiff;
}
答案 0 :(得分:2)
0x80000000不在int
范围之外。 int
取决于平台,并且存在int
为32位宽的平台。这个数字是32位宽,因此它将对int
进行“直接位分配”。
是的,这个数字的十进制表示是2^31
但是只有当你将这些位解释为unsigned
时才会这样,这在比特的情况下是没有意义的。你真的需要查看L值才能知道它将被处理为什么,这是一个签名的int
/
现在,假设这是一个32位平台,这是编写MIN_INT的一种奇特方式,而且看上去很简单,我的意思是非便携式,需要很多不一致的假设,最后让那些不知所措的人感到困惑我不想做二进制数学。它假定2的补码数学,并选择直接设置位。
基本上,使用2的补码数,零仍然是
0x00000000
但要获得-1 + 1 = 0
,你必须得到一些东西要添加到1 yeilding 0
0x????????
+ 0x00000001
= 0x00000000
所以你选择
0x11111111
+ 0x00000001
= 0x00000000
依靠携带1来最终走出尽头。然后你可以推断出1低于-2,依此类推;最多到-2 = 0x11111110
点等等。基本上,因为第一位确定了数字的“符号”,你可能拥有的“最大”负数是0x1000000
,如果你试图从中减去1,你将从“负”符号位开始产生最大的正数。 0x01111111
。
答案 1 :(得分:1)
如果常量在您的平台上具有类型unsigned int
并且该函数被声明为返回int
,那么unsigned int
值将隐式转换为类型int
。如果原始值不适合int
范围,则此转换的结果是实现定义的(或者它可能会引发信号)。
6.3.1.3有符号和无符号整数
3 否则,新类型已签名且值无法在其中表示;结果是 实现定义或实现定义的信号被引发。
请参阅编译器文档,了解在这种情况下会发生什么。显然,代码的作者得出的结论是,实现完全符合他们的要求。例如,一种自然的事情是某些实现将这个位模式“重新解释”为有符号整数值,其中最高位成为符号位。它会在具有32位0x80000000
s的二进制补码平台上将INT_MIN
转换为int
值。
答案 2 :(得分:0)
这是一种错误的做法,应该更正返回值
代码返回二进制10000000 00000000 00000000 00000000
和
在sizeof(int)= 4byte:
的机器上int
将其视为二进制10000000 00000000 00000000 00000000
=整数-2147483648
(负值)。unsigned int
,则会将0x80000000
视为二进制10000000 00000000 00000000 00000000
=整数2147483648
在sizeof(int)= 2byte:
的机器上