本文由C语言实现。
目录
前言
数据类型之间的转换包含强制类型转换与自动类型提升,而数据在内存中的存储方式也存在溢出、截断的问题。这样的问题比较隐蔽,在实际做题时往往稍不留心,就会犯错(而且常常错答与标答差十万八千里)。
本文整理了与“数据在内存中的存储”知识点相关的易错题,并在习题前附带了基础知识的简述。对该部分基础知识仍有疑问的同学可以移步至其它博主发表的该知识点基础知识详解博客。浮点数的存储与习题本文中不涉及。
本文以习题解析为主,供大家参考学习,希望有所帮助。
一、引例
有如下代码,运行后程序将输出怎样的结果?
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)位用来表示数值。因而它能表示的范围为:~
.正数方面之所以要减一,是因为其中还有个0在中间。
(注意:当二进制补码满位,而最左位是1,后面为全0时,该数表示 ,而不是负0。注意在补码表示法中只有一个0,如char类型存储二进制1000 0000,表示的不是十进制的-0,而是-128)。
如有符号的char类型,可表示的范围为到
(-128到127)
无符号数的取值范围则是0到,因为它没有符号位,所有的数位(n)都用以表示数值。之所以还要减一,是因为范围从0开始。
如无符号的char类型,可表示的范围为0到(0到255)
二、详解:溢出
因为大小(即存储单元的位的数量)的限制,可以表达的整数范围是有限的。
1. 无符号数的溢出
在n位存储单元中,我们可以存储的无符号整数可表示的整数仅为0到-1之间。如果超出了上限
-1,就会发生溢出。
下面的罗盘图显示了如果在仅为4位的内存中,存储大于15(即-1)的整数的情况。当已经存了整数11后,又再加上9,得到的结果21超出了可存储的最大值15,这时发生溢出。

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