为什么'%d'没有返回正确的价值?

时间:2015-03-23 16:20:01

标签: c int

int a = 31; 
int b = 1; 

while (a)
{
    b = (2 * b) + 1;
    a--;
};

printf("count:%d \n", b);

a小于31时,它会输出正确的数字。从31开始,它只打印-1,我不明白为什么。我该如何解决?

4 个答案:

答案 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-12^32溢出4字节整数存储类型,导致未定义的行为。但是一些编译器通常只是丢弃溢出的最左边的位来处理溢出,因此截断的2^32变为0。所以0-1 = -1这就是你的结果。但同样,没有标准可以保证你会得到这个结果,所以你永远不要依赖它。
要解决此问题,您可以使用更大的存储类型,例如long,并将%ld用于printf

答案 3 :(得分:0)

没关系@EugeneSh。回答,但系列不是从1开始,而是3.并且要打印b的所有值,printf需要保持while循环。如果意图从1开始,则printf需要是第一个进入while循环。