1字=1字节(1 word=2 byte),1字节=8位(1 byte=8 bit),字节是机器最小可寻址的内存单位,不是内存中单独的位。
一个字节由8位组成。在二进制表示法中,它的值域为00000000~11111111,如果看成十进制整数,它的值域就是0~255,如果用十六进制书写的话,它的值域就是00~FF。其中A~F大小写都没有问题。在二进制转化为十六进制上,首先将二进制分为4位一组,如果不够四位的话补零,例如:0011.1011 1000,转化的结果就是3.B8。转化回去就是一个逆过程。十进制转化为十六进制可以采用先转化为二进制或者除以16取余操作。
大多数64位机器可以运行32位机器编译的程序,这是一种向后兼容。编译指令为:linux> gcc -m32 prog.c或gcc -m64 prog.c
这一节是大端法和小端法。假设变量x的类型为int,位于地址0x100处它的十六进制为0x01234567。地址范围为0x100~0x103的字节顺序依赖于机器类型:
大小端 | … | 0x100 | 0x101 | 0x102 | 0x103 | … |
---|---|---|---|---|---|---|
大端法 | … | 01 | 23 | 45 | 67 | … |
小端法 | … | 01 | 23 | 45 | 67 | … |
C语言中字符串被编码为一个以null(其值为0)字符结尾的字符数组。
没啥要说的
布尔代数只有两种形态:对与否(1,0)。
C语言中位级运算例子:
C语言提供了一组逻辑运算符||、&&、!,功能和位级运算不要弄混
这个看看例子就行了
对于有符号数,最高位是符号位,例如上面的0101最高位是0,是正数;1011最高位为1,是负数。
若一个运算为有符号数和无符号数的运算,那么C语言会隐式的将有符号数强制转化为无符号数来执行运算,例如:
int a = -1;
unsigned int b = 0;
if (a < b)
printf("-1 < 0");
else
printf("-1 > 0");
对于无符号数来说,直接补零就可以了,但是对于有符号数来说,如下:
符号位扩展保持数值不变的证明,大体思路就是假如能够证明符号位扩展一位,可以保持数值不变就可以了:
将一个w为的无符号数,截断成k位时,丢弃最高的w-k位,截断操作可以对应于取模运算,对于二进制取模,通俗来讲就是除以2的k次方之后得到的余数
有符号数截断之后成了无符号数,然后将无符号数转化为有符号数
下图展示是如何溢出的:
有符号的溢出分为正溢出和负溢出
下面是检测有符号数相加是否发生溢出:
对于减法,书本中提到了一个概念叫做加法逆元,通俗点就是相反数,即x+x’=x’+x=0;
在C语言中的无符号乘法被定义为产生w位的值,就是2w位的整数乘积的低w位表示的值:
乘法可以通过移位操作
对于无符号数采用的是逻辑右移,对于有符号数采用的是算术右移。。
某些浮点数(eg.0.1)在计算机内不能精确表示(eg.3.1f + 2.1f != 5.2f)会丢一些有效位
浮点数在计算机中包括三个部分:
float和double的各位如下:
规格化、非规格化、无穷大、NAN:
当阶码字段的二进制不全为0且不全为1时,此时表示的是规格化的值。
当阶码字段的二进制全为1时,此时表示的是非规格化的值
当阶码字段的二进制全为1时,表示的是特殊值,这里的特殊值分为无穷大和不是一个数,不是一个数就比如-1开方等等。
如下图表示:
下面来详细解释一下这三种数值的表示:
单精度浮点中,当表示规格化的时候,阶码e的范围为00000001~11111110,即最小值为1,最大值为254,但是
这个e并不是阶码的值,而是e值减去一个偏置量,偏置量的值与编码字段的位数是相关的,如下所示,大E就是阶码值:
再来看看小数部分,尾数M被定义为1+f,尾数M的二进制表示:M=1.f22f21…f1f0=1+f,1<=M<2,在知道M、E、S之后就可以求得浮点数的值了
当阶码字段的二进制位全为0时,所表示的是非规格化的值,关于非规格化的数有两个用途,一是提供了表示数值0的方法,当符号位S等于0,阶码字段全为0,小数字段也全为0时,此时表示的正零;当符号位S等于1,阶码字段全为0,小数字段也全为0时,此时表示负零。非规格化的是的另外一个用途就是可以表示一个非常接近于0的数
无穷大:符号位0时,表示正无穷大,为1时,表示负无穷大。
不为一个数:-1开方,∞-∞等。
float:0xC0A00000
二进制表示:1100 0000 1010 0000 0000 0000 0000 0000
符号位 | 阶码位 | 尾数位 |
---|---|---|
1 | 1000 0001 | 010 0000 0000 0000 0000 0000 |
E=129-127=2
S=1 负数
M=1. 010 0000 0000 0000 0000 0000=1.25
所以V=-1*1.25*2^2=-5
十进制数:-12.75
化为二进制为:1100.11
转化:1.10011*2^3
所以阶码位=127+3=1000 0010
尾数位为:10011 00000…
最后:
符号位 | 阶码位 | 尾数位 |
---|---|---|
1 | 1000 0010 | 100 1100 0000 0000 0000 0000 |
Hex:C14C0000
以float为例子,有一个整型数12345,它的二进制为11 0000 0011 1001(只看有效位),由于M=1+f,所以
f=100 0000 1110 0100 0000 0000
12345=1.1000000111001*2^13得到E=13,所以得到e=140=10001100,最后加上符号位0
由于浮点数位有限,存在一个表示范围和精度的问题,对于数值x,只能用浮点数可以表示的最接近数值x‘来近似表示,这就是舍入。IEEE规定了4种舍入的方法,分别是:向0舍入、向下舍入、向上舍入、向偶数舍入。
向0舍入就是在数轴上,舍入方向总是向0的,例如1.4->1、-1.5->-1
向下舍入就是朝着小的方向舍入
向上舍入就是朝着大的方向舍入
向偶数舍入有两个原则,一是向最接近的值舍入,再一个是当处在"中间值"时要求有效位为偶数,就是舍去或进位之后最右边那一位为偶数。
阶码对齐,尾数相加(相乘),规格化,若超过有效位进行舍入。
数的范围double>float>int
图片来源http://t.csdnimg.cn/flJZL