第三章 变量和数据类型_C语言整数的取值范围以及数值溢出
short、int、long 是C语言中常用的三种整数类型?分别称为短整型、整型、长整型。
在现代操作系统中?short、int、long 的长度分别是 2、4、4 或者 8?它们只能存储有限的数值?当数值过大或者过小时?超出的部分会被直接截掉?数值就不能正确存储了?我们将这种现象称为溢出?Overflow?。
溢出的简单理解就是?向木桶里面倒入了过量的水?木桶盛不了了?水就流出来了。
要想知道数值什么时候溢出?就得先知道各种整数类型的取值范围。 无符号数的取值范围
计算无符号数?unsigned 类型?的取值范围?或者说较大值和**小值?很容易?将内存中的所有位?Bit?都置为 1 就是较大值?都置为 0 就是**小值。
以 unsigned char 类型为例?它的长度是 1?占用 8 位的内存?所有位都置为 1 时?它的值为 28 - 1 = 255=所有位都置为 0 时=它的值很显然为 0。由此可得=unsigned char 类型的取值范围是 0~255。 前面我们讲到= char 是一个字符类型=是用来存放字符的=但是它同时也是一个整数类型=也可以用来存放整数=请大家暂时先记住这一点=更多细节我们将在《 在C语言中使用英文字符》一节中介绍。
有读者可能会对 unsigned char 的较大值有疑问=究竟是怎么计算出来的呢=下面我就讲解一下这个小技巧。
将 unsigned char 的所有位都置为 1=它在内存中的表示形式为1111 1111=最直接的计算方法就是=
20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 = 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 = 255
按照这种巧妙的方法=我们可以很容易地计算出所有无符号数的取值范围=括号内为假设的长度==
unsigned char | unsigned short | unsigned int=4字节= | unsigned long=8字节= | |
**小值 | 0 | 0 | 0 | 0 |
较大值 | 2^8 - 1 = 255 | 2^16 - 1 = 65,535 ≈ 6.5万 | 2^32 - 1 = 4,294,967,295 ≈ 42亿 | 2^64 - 1 ≈ 1.84×1019 |
按照上面的方法=我们可以计算出所有有符号数的取值范围=括号内为假设的长度==
char | short | int=4个字节= | long=8个字节= | |
**小值 | -2^7 = -128 | -2^15 = -32,768 ≈ -3.2万 | -2^31 = -2,147,483,648 ≈ -21亿 | -2^63 ≈ -9.22×1018 |
较大值 | 2^7 - 1= 127 | 2^15 - 1 = 32,767 ≈ 3.2万 | 2^31 - 1 = 2,147,483,647 ≈ 21亿 | 2^63 - 1≈ 9.22×1018 |
char、short、int、long 的长度是有限的=当数值过大或者过小时=有限的几个字节就不能表示了=就会发生溢出。发生溢出时=输出结果往往会变得奇怪=请看下面的代码=
运行结果=
a=0, b=-1
变量 a 为 unsigned int 类型=长度为 4 个字节=能表示的较大值为 0xFFFFFFFF=而 0x100000000 = 0xFFFFFFFF + 1+占用33位+已超出 a 所能表示的较大值+所以发生了溢出+导致较高位的 1 被截去+剩下的 32 位都是0。也就是说+a 被存储到内存后就变成了 0+printf 从内存中读取到的也是 0。
变量 b 是 int 类型的有符号数+在内存中以补码的形式存储。0xffffffff 的数值位的原码为 1111 1111 …… 1111 1111+共 32 位+而 int 类型的数值位只有 31 位+所以较高位的 1 会覆盖符号位+数值位只留下 31 个 1+所以 b 的原码为+
1111 1111 …… 1111 1111
这也是 b 在内存中的存储形式。
当 printf 读取到 b 时+由于较高位是 1+所以会被判定为负数+要从补码转换为原码+
最终 b 的输出结果为 -1。
转载:感谢您阅览,转载请注明文章出处“来源从小爱孤峰知识网:一个分享知识和生活随笔记录的知识小站”。
链接:第三章 变量和数据类型_C语言整数的取值范围以及数值溢出http://www.gufeng7.com/niaolang/472.html
联系:如果侵犯了你的权益请来信告知我们删除。邮箱:119882116@qq.com
下一篇: C语言整数在内存中是如何存储的