Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么';%d';不返回正确的值?_C_Int - Fatal编程技术网

C 为什么';%d';不返回正确的值?

C 为什么';%d';不返回正确的值?,c,int,C,Int,当a小于31时,它会打印正确的数字。从31开始,它只打印-1,我不明白为什么。如何修复它?整数溢出并将变为负数 要解决此问题,可以将int变量b更改为long int a = 31; int b = 1; while (a) { b = (2 * b) + 1; a--; }; printf("count:%d \n", b); 整数溢出并将变为负数 要解决此问题,可以将int变量b更改为long int a = 31; int b = 1; while (a)

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

整数溢出并将变为负数

要解决此问题,可以将
int
变量
b
更改为
long

int a = 31; 
int b = 1; 

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

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

整数溢出并将变为负数

要解决此问题,可以将
int
变量
b
更改为
long

int a = 31; 
int b = 1; 

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

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

在int类型的两个补码内部表示中,如果其大小等于4字节,则符号位等于2^31

因此,当b等于INT_MAX时,将b乘以2,然后设置符号位并将数字转换为-1


也就是说,当符号位未设置时,会得到泊松数1、3、7、15等等。一旦设置了符号位,您就会得到负数-1,该负数具有内部表示形式,所有位(包括符号位)都已设置。

在int类型的两个补码内部表示形式中,如果其大小等于4字节,则符号位等于2^31

因此,当b等于INT_MAX时,将b乘以2,然后设置符号位并将数字转换为-1


也就是说,当符号位未设置时,会得到泊松数1、3、7、15等等。一旦设置了符号位,您就会得到负数-1,该负数具有内部表示形式,包括符号位在内的所有位都已设置。

a
变为0时,由于条件

long b = 1;
评估

 while (a) ...
它将在循环执行
31次后发生,其中包含以下表达式:

while (a != 0)...
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

循环在
a
变为0时终止,因为条件为

long b = 1;
评估

 while (a) ...
它将在循环执行
31次后发生,其中包含以下表达式:

while (a != 0)...
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

可以使用@EugeneSh。答案是,但是这个系列不是从1开始,而是从3开始。要打印b的所有值,printf需要保留在while循环中。如果打算从1开始,printf需要是while循环中的第一行。

可以使用@EugeneSh。答案是,但是这个系列不是从1开始,而是从3开始。要打印b的所有值,printf需要保持在while循环中。如果打算从1开始,printf需要是while循环的第一行。

在最后一次迭代开始时
b
2147483647
,因此
2*b
将是未定义的行为,并可能导致
-2
,这将导致在最后一次迭代后
b
等于
-1
。该程序永远不会计算
0-1
以获得
b
@mch您是对的。通过编译器,大多数情况下都是这样工作的。我将编辑答案。@EugeneSh。无符号整数溢出定义良好(模运算),但有符号整数溢出是UB。在上一次迭代开始时,
b
2147483647
,因此
2*b
将是未定义的行为,可能导致
-2
,这将导致在上一次迭代后
b
等于
-1
。该程序永远不会计算
0-1
以获得
b
@mch您是对的。通过编译器,大多数情况下都是这样工作的。我将编辑答案。@EugeneSh。无符号整数溢出是定义良好的(模运算),但有符号整数溢出是UB。如果你仔细看,我的回答是,序列从迭代数
0
开始,这是
b
的初始值,对不起,@EugeneSh,我没有看到。如果你仔细看,我的回答是,这个系列是从迭代编号
0
开始的,这是
b
的初始值,对不起,@EugeneSh,我没有看到,我已经更新了我的答案。现在它确实解释了如何修复它:)当您在while循环中添加printf语句来打印bI have updated my answer的计算值时,问题将变得很明显。现在它确实解释了如何修复它:)当您在while循环中添加printf语句以打印b的计算值时,问题将变得很明显