我正在研究K& R的练习2-1,目标是计算不同变量类型的范围,下面是我计算short int
可以包含的最大值的函数:
short int max_short(void) {
short int i = 1, j = 0, k = 0;
while (i > k) {
k = i;
if (((short int)2 * i) > (short int)0)
i *= 2;
else {
j = i;
while (i + j <= (short int)0)
j /= 2;
i += j;
}
}
return i;
}
我的问题是这个函数返回的值是:-32768
这显然是错误的,因为我期待一个正值。我无法弄清楚问题出在哪里,我使用相同的函数(在变量类型中有变化)来计算int可以包含的最大值并且它有效...
我虽然问题可能是由于if
和while
语句中的比较造成的,因此类型转换却没有帮助......
任何想法导致了什么?提前谢谢!
编辑:感谢Antti Haapala的解释,符号位的溢出会导致未定义的行为,而不是负值。
答案 0 :(得分:5)
您无法使用此类计算来推断 signed signed 的范围,因为有符号整数溢出具有未定义的行为,并且在实现中最大限度地缩小转换结果 - 定义的值,或者引发的信号。正确的解决方案是使用SHRT_MAX
的{{1}},INT_MAX
...。通过算术推导有符号整数的最大值是标准化C语言中的一个棘手问题,自1989年第一个标准出版以来就一直如此。
请注意,K&amp; R的原始版本比C的标准化早了 11 年,甚至第二一个 - “ANSI-C”版本早于最终标准并且与它有所不同 - 它们是为一种语言而写的,这种语言几乎不是完全不同于今天的C语言。
您可以轻松地对无符号整数执行此操作:
<limits.h>
答案 1 :(得分:0)
根据定义,您无法使用相同类型的变量计算C中类型的最大值。它根本没有任何意义。当它“越过顶部”时,该类型将溢出。在有符号整数溢出的情况下,行为是未定义的,这意味着如果你尝试它会遇到一个主要的错误。
执行此操作的正确方法是从limits.h中检查SHRT_MAX
。
另一种更有问题的方法是创建unsigned short
的最大值然后将其除以2.我们可以通过对值0进行按位求逆来创建最大值。
#include <stdio.h>
#include <limits.h>
int main()
{
printf("%hd\n", SHRT_MAX); // best way
unsigned short ushort_max = ~0u;
short short_max = ushort_max / 2;
printf("%hd\n", short_max);
return 0;
}
关于您的代码的一个注释:
((short int)2*i)>(short int)0
等演员阵容完全是多余的。 C中的大多数二元运算符(例如*
和>
)实现了一种称为“通常的算术转换”的东西,这是一种隐式转换和平衡表达式类型的方法。这些隐式转换规则将静默地使两个操作数类型int
尽管你的演员阵容。
答案 2 :(得分:-2)
你忘了在比较期间转换为短整数
好的,在这里我假设计算机会通过改变为负整数来处理整数溢出行为,因为我相信你已经在编写这个程序。
输出32767的代码:
car
添加了2个演员