C语言再学习part4—数据类型(一)
我与众人本不同,依道而生依道死。 --《寂寞圣哲》
C语言系列又回来了!是不是很开心。在我整理硬件知识的时候,我发觉硬件知识不像C语言有着系统的前人的理论体系。硬件知识是很碎的,并且由于现在网络太发达,再加上现在很多人不愿意沉下心去搞技术,所以网页上的很多东西都是你抄我的,我抄你的。我看到的真正写点经验的网页或者帖子是有的,但是不太多。所以我想对自己说的是,自己吸收知识时必须持有批判精神,无论是网上的还是书本上的。并且自己对自己的博文要保持严谨端正的态度,不可敷衍了事。如果我们这些未来的科技人都在糊弄,都在敷衍,中国科技的发展又能靠谁呢?
好了,言归正传。该篇文章主要梳理C语言中的数据类型的知识。我觉得学会了C语言中的数据类型,那么C语言就算入门了。
首先来说一下数值转换。
我们假设16字节的处理器,基本整型的长度为16位。表示的数的范围是有限的。十进制无符号整型常数的模(范围)是65536个(2的16次方),其中范围是0-65535,有符号数为-32768-32767。八进制无符号数0-0177777,八进制有符号数1 777 777 777 777 777 700 000- 77 777,十六进制无符号数表示范围0-0Xffff,十六进制有符号0xFFFF FFFF FFFF 8000- 0x7FFF。这里有个技巧分享给大家,如果说n位的二进制数,那么这个二进制数最大值为(2^n)-1,最小值为0,模(范围)是2^n,这是为什么呢?如果是个8位的二进制数,它的最大值为11111111,普通的方法就是2^7+......+2^0=255。但是如果我们把它加上1后,是不是变成了9位数100000000,那么这个数的计算式不就是简单很多了,只有2^8=256了?由于第一位是0位,所以我们采用加一的方式将2的指数与数的位数对应。也就是说,我们加上1后2的指数变成了数的位数为8。综上,我们可以看到8位数的最大值为256-1=255,最小值固定的是0。并且255是由0为基准,所以它的模为256。
其中整型数据在内存中的存放方式—数值的补码。对于整型常量的存放是采用32位补码的形式存放的,例如int a=3中的3就是以32位的补码方式存放的。对于整型变量是采用赋予数据结构的类型存放的。
在这里,我要多拓展一下补码、反码、原码的知识。其中,正数的补码、反码、原码是相同的。负数的反码是求出原码(符号位不动为1),其他位置在原码上符号位不动取反,其补码是在反码上加1而得到。补码还有一种算法就是负数的补码是它的模减去它的绝对值,或说是它本身加上它的模。给你一个补码形式的数,让你求它的模,就把符号位往前进一位,这一位的值就是它的模。
那么,为什么计算机数据存放形式采用补码呢?补码是为了解决负数在计算机中的表示问题,最终是为了解决计算机的减法运算问题。人类需要对数值进行加减乘除运算,计算机被发明之初就是用来解决这个问题的,人类先是发明了加法器,如果将乘法看作是累加(移位,逻辑判断,累加),那么加法问题解决了,乘法问题也就解决了。
那也就是说:如果减法问题解决了,除法问题也就解决了(移位,逻辑判断,累减)。
解决思路就是找到负数绝对值的相反数来表示就可以了。
步骤如下:
例如表示负0001
一般我们的思路是,找一个数,跟0001相加的结果等于0就可以找到他的相反数。那就找出一个与它相加后结果是 1111 1111的数(这应该就是反码的来历),然后该数+1(+1溢出,所以相加的和就是0)即是我们所要的答案(这应该就是补码的来历)。
所以很容易得出:
a=0000 0001(1) // 以8位数据为例 0000 0001 + 1111 1110 // 先找出与a相加为1111 1111的数(a的反码) = 1111 1111 1111 1110 + 1 = 1111 1111 // 这个数再加1就是我们要找的数(与a相加为0的数) 0000 0001 // a + 1111 1111 // 与a相加为0的数(a的补码) = (1)0000 0000 0000 0000
所以,在不改变计算机的电子操作层面只有与的操作,并且不需要设计专门的数字处理信号电路。所以使用补码加上标记位可以将与操作变成加法。
加法器解决了加法和乘法运算问题,补码解决了减法和除法运算问题。
其实中央处理器做二进制除法的时候,是让被除数连续减去几次除数,直到差小于除数时为止,这样减去的次数就是商,剩下的差就是余数。如果余数为零,说明被除数能被除数整除,这时的被除数叫做除数的倍数,除数叫做被除数的约数。乘法和这个过程相反。只是不同的数存放在不同寄存器中罢了。[1]
参考链接:[1]https://www.zhihu.com/question/335614901/answer/755608419