int a = 31;
int b = 1;
while (a)
{
b = (2 * b) + 1;
a--;
};
printf("count:%d \n", b);
当a
小于31
时,它会输出正确的数字。从31
开始,它只打印-1
,我不明白为什么。我该如何解决?
答案 0 :(得分:2)
整数溢出并将变为负数。
要解决此问题,您可以将int
变量b
更改为long
。
long b = 1;
答案 1 :(得分:1)
在int类型的补码内部表示中,如果其大小为equl到4个字节,则符号位等于2 ^ 31。
因此,当b等于INT_MAX时,将b乘以2,然后设置符号位并将数字转换为-1。
也就是说,当符号位未设置时,您将获得有用的数字1,3,7,15等等。一旦设置了符号位,就会得到负数-1,它具有内部表示,所有位都包括符号位。
答案 2 :(得分:1)
while
循环在a
变为0时终止,因为条件
while (a) ...
评估
while (a != 0)...
循环执行31
次后会出现以下表达式:
b = (2 * b) + 1;
虽然b
的初始值为1
。它将生成系列:1, 3, 7, 15... 2^(k+1)-1
,而k
是迭代编号(从初始值的0开始)。因此,对于k = 31
,该值将为2^32-1
。 2^32
溢出4字节整数存储类型,导致未定义的行为。但是一些编译器通常只是丢弃溢出的最左边的位来处理溢出,因此截断的2^32
变为0
。所以0-1 = -1
这就是你的结果。但同样,没有标准可以保证你会得到这个结果,所以你永远不要依赖它。
要解决此问题,您可以使用更大的存储类型,例如long
,并将%ld
用于printf
。
答案 3 :(得分:0)
没关系@EugeneSh。回答,但系列不是从1开始,而是3.并且要打印b的所有值,printf需要保持while循环。如果意图从1开始,则printf需要是第一个进入while循环。