为什么涉及变量的操作不会在C中溢出

时间:2019-01-29 03:17:00

标签: c

我在C中有一个类似这样的代码:

int main(){
   unsigned char var1;

   var1 = 255;
   var1 = var1 + 1;

   printf("The result is = %i", var1);

}

我认为它会溢出,因为var1的最大类型最多为255,因此当将其递增为1时,它将为256,但结果为0。

但是当我修改代码时,就像这样:

int main(){
   unsigned char var1;

   var1 = 255+ 1;

   printf("The result is = %i", var1);

}

结果给出了一个溢出错误,例如“警告:从'int'到'unsigned char'的无符号转换将值从'256'更改为'0'[-Woverflow]”。

为什么第一代码不会溢出?

2 个答案:

答案 0 :(得分:6)

无符号字符(本质上是一个字节)的环绕是设计使然。

但是,您的第二个示例将添加两个int。从int的256转换为字节的零会构成信息丢失;因此是警告。

答案 1 :(得分:4)

  

为什么第一代码不会溢出?

第一个代码的溢出与第二个代码的溢出完全相同,并且在完全相同的位置:将总和分配给变量var1

在第一个示例中,无符号字符var1的初始值255被转换为类型int并向其添加1。然后将得到的int值256转换为类型unsigned char,根据定义,该类型涉及将其取模256, * 得出0。第二个示例完全相同,除了左操作数已经是int 255,不需要转换。计算出完全相同的总和,并执行到unsigned char的完全相同的转换。一种情况下发生的溢出量与另一种情况一样。

区别仅在于您的特定编译器认为适当的警告范围。完全没有义务在此处发出任何警告,它自行决定选择第二个版本发出警告,而第一个版本不发出警告。

也许它认为第二个错误比第一个错误更可能构成编程错误(合理),并且警告之间的适当阈值介于(有争议的)之间。也许,就像@RobertHarvey在评论中建议的那样,它没有足够深入地分析代码,以至于在这种情况下,表达式var1 + 1肯定溢出了。


* 更一般而言,转换涉及将结果以模形式比结果类型的最大可表示值unsigned char减少一。您有8位unsigned char,这很正常。它们的范围是0-255,因此减少的模数是256。类似的情况适用于所有其他无符号整数类型的转换,以及实际上已完成的无符号类型的算术运算。