溢出、截断、类型提升:从易错代码入手分析整型数据存储与类型转换

本文由C语言实现。


目录

前言

一、引例 

有如下代码,运行后程序将输出怎样的结果?

二、简述:整型在内存中的存储

1.整型的存储方式

2.基本内置类型及其取值范围

3.取值范围

二、详解:溢出

1. 无符号数的溢出

2.有符号数的溢出

正数溢出

负数溢出

2.小结 

三、详解:整型的数据类型转换

1.自动类型转换

赋值时发生的自动类型转换

运算时发生的自动类型转换

2.强制类型转换

四、练习题:陷阱何处来

1.练习1:引例

2.练习2

3.练习3

4.补充练习-1

5.补充练习-2

6.补充练习-3

7.补充练习-4

8.补充练习-5

9.补充练习-6

10.补充练习-7 

五、总结与回顾


前言

数据类型之间的转换包含强制类型转换与自动类型提升,而数据在内存中的存储方式也存在溢出、截断的问题。这样的问题比较隐蔽,在实际做题时往往稍不留心,就会犯错(而且常常错答与标答差十万八千里)。

本文整理了与“数据在内存中的存储”知识点相关的易错题,并在习题前附带了基础知识的简述。对该部分基础知识仍有疑问的同学可以移步至其它博主发表的该知识点基础知识详解博客。浮点数的存储与习题本文中不涉及。

本文以习题解析为主,供大家参考学习,希望有所帮助。


一、引例 

有如下代码,运行后程序将输出怎样的结果?

int main()
{
  unsigned char a = 200;
  unsigned char b = 100;
  unsigned char c = 0;
  c = a + b;
  printf(“%d %d”, a+b,c);
  return 0;
}

 解题方式在文末。


 

二、简述:整型在内存中的存储

1.整型的存储方式

尽管计算机打印让我们看到的是原码,但整型其实以二进制补码的方式存储在内存中,整形表达式计算使用的也是内存中存储的补码。

一个数的原码则是这个数直接转换成二进制,反码是原码的二进制符号位不变,其他位按位取反。

正数:补码=反码=原码

负数:补码=反码+1=原码按位取反+1

对于符号数(signed)而言,左边第一位二进制位为符号位,0表示正,1表示负,其余为数值位,存储实际的数值;

对于无符号数(unsigned)而言,所有的数位都是数值位,没有符号位。

特别注意:在进行加法减法等运算时,符号位也是参与运算的。 


 

2.基本内置类型及其取值范围

3.取值范围

有符号数以其左边第一位是符号位,不计入数值计算。故 n 位有符号数,只有(n-1)位用来表示数值。因而它能表示的范围为:-2^{n-1}~2^{n}-1 .正数方面之所以要减一,是因为其中还有个0在中间。

注意:当二进制补码满位,而最左位是1,后面为全0时,该数表示 -2^{n-1},而不是负0。注意在补码表示法中只有一个0,如char类型存储二进制1000 0000,表示的不是十进制的-0,而是-128)。

如有符号的char类型,可表示的范围为-2^{7}2^{7}-1(-128到127)

无符号数的取值范围则是0到2^{n}-1,因为它没有符号位,所有的数位(n)都用以表示数值。之所以还要减一,是因为范围从0开始。

如无符号的char类型,可表示的范围为0到2^{8}-1(0到255)


二、详解:溢出

因为大小(即存储单元的位的数量)的限制,可以表达的整数范围是有限的。

1. 无符号数的溢出

在n位存储单元中,我们可以存储的无符号整数可表示的整数仅为0到2^{n}-1之间。如果超出了上限2^{n}-1,就会发生溢出。 

下面的罗盘图显示了如果在仅为4位的内存中,存储大于15(即2^{4}-1)的整数的情况。当已经存了整数11后,又再加上9,得到的结果21超出了可存储的最大值15,这时发生溢出。

无符号整数溢出 -- 罗盘图

 

表示十进制数20的最少需要5位,即20 = 10100b,而该计算机只能存4位,因此,计算机会丢掉最左边的位,并保留最右边的4位0100b。计算机会将0100b当成一个无符号整数解析成十进制的

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值