C 语言数的表示(一)
c语言整数表示
写文章的目的在于整理c语言整数溢出时出现的知识。
数据类型与表示方法
c语言中基本数据类型的表示有整型和浮点型,整型有short,int,long,还有一个修饰词,unsigned,即无符号。声明一个变量,即向内存申请一段数据类型相对应的存储地址,申请的变量类型及分配的内存大小,可以通过sizeof函数来得出。输出结果如下列表所示:
Type short has a size of 2 bytes.
Type int has a size of 4 bytes.
Type long has a size of 8 bytes.
Type float has a size of 4 bytes.
Type double has a size of 8 bytes.
Type long long has size of 8 bytes
由此可看到各个不同类型数在系统申请内存的字节数。内存中存储的二进制值为机器数,其通过表示方法对应为十进制的真值。
机器数和真值
机器数和真值,在上面所列出的数据类型中,如short类,在内存申请的存储空间为2字节,即16bit位。在表示中,高位为符号位,0为正数,1为负数。
假定8位表示一个数,如数字7,为正数,转换为二进制为00000111,如果是-3,负数首位为1,转换为二进制为10000111。
如上3,-3为真值,00000111/10000111为其对应的机器数。
原码、反码、补码
原码
原码为符号位+真值的绝对值,如[+1]原=00000001,[-1]原=10000001,则8位二进制原码取值范围为:[11111111-011111111],即[-127~+127]。
反码
反码为正数的反码为其原码,负数的反码为在其原码的基础上,符号位不变,其余位依次取反。如[+1]反=00000001,[-1]反=11111110。
补码
正数的被码为其原码,负数的补码为反码+1,如[+1]补=00000001,[-1]补=11111111。
采用不同编码方式的原因
计算机中,因保持电路简单的设计,计算机只能执行简单的加法运算,减法运算,可以让参数符号位参与运算,即+负数。
如上描述中,计算1-1=0,对应的机器数原码操作为:
[00000001]原+[10000001]原=[10000010]原=[-2]真,对应的真值为-2。即参与负数计算的真值中不正确的。
如使用反码参与减法计算,1-1则对应的机器数反码操作为:
[00000001]反+[11111110]反=[11111111]反=[10000000]原=[-0]真,让符号位参与运算,得到为-0的真值,即反码操作中,存在一个为-0的问题,-0是没有意义的,而原码和反码本身即都存在±0的表示。
为了解决±0的问题,即补码出现:
1-1=1+(-1)=》[00000001]原+[10000001]原=》[00000001]补+[11111111]补=》[00000000]补=[00000000]原=[0]真。
即[00000000]表示0,同时可以使用[10000000]表示[-128]
即[-1]+[-127]=》[10000001]原+[111111111]原=》[11111111]补+[10000001]补=》[10000000]原。即使用-0的原码表示-128的补码。
实际-128没有原码和反码的对应值,使用补码不仅修复了原码和反码中存在0和计算的问题,还可以多使用一个低位数值,8位原码和反码的表示范围为[-127+127],补码的表示范围为[-128+128]。
即采用补码计算中,数值的取值范围为[-2^(n-1)~2^(n-1)-1]。(n为位数)