2.1 信息存储
大多数计算机使用字节(byte)作为最小的可寻址的内存单位,内存的每个字节都由一个唯一的数字来标识称为它的地址。
2.1.1 十六进制表示法
1字节=8位(1byte=8bit)
二进制表示法中一个字节的值域是00000000~11111111,十进制表示法中一个字节的值域是0~255,十六进制表示法中一个字节的值域是00~FF(也就是说一个字节用两位十六进制就可以表示)。
十六进制以0x或者0X开头(数字0),字符A~F不区分大小写。
以下只考虑不带符合的正整数
十六进制和二进制之间的转换:十六进制的一位对应二进制的四位
十六进制转二进制:将十六进制数0x173A4c转为二进制数0001 0111 0011 1010 0100 1100
二进制转十六进制:将二进制数11 1100 1010 1101 1011 0011转为十六进制数3CADB3(二进制数位数不是4的倍数最左边一组不足4位前面补0)
十六进制和十进制之间的转换:
十六进制转十进制:十六进制数0x7AF转为十进制数7*16^2+10*16+15=1967
十进制转十六进制:十进制数314156转为十六进制数,314156=19634*16+12(C),19634=1227*16+2(2),1227=76*16+11(B),76=4*16+12(C),4=0*16+4(4),即0x4CB2C
二进制和十进制之间的转换:
二进制转十进制:先补齐二进制数位数,首位为0是正整数,首位为1是负整数,如二进制数1100,补齐位数为0000 1100,转为十进制2^3+2^2=12
十进制转二进制:十进制数125转为二进制数,125=2*62+1(1),62=2*31+0(0),31=2*15+1(1),15=2*7+1(1),7=2*3+1(1),3=2*1+1(1),1=2*0+1(1),即0111 1101,最左边一位补0
十进制转二进制和十六进制的特殊情况:当要转换的数x(十进制)是2的非负整数n次幂时,比如当x=2048(2048是2的11次幂,2048=2^11),x的二进制表示就是1后面跟n个0,即1000 0000 0000,
x的十六进制表示就是(n=i+4j,0<=i<=3,i,j都是正整数),所以n=11,i=3,j=2,十六进制数为2的3(i)次幂后加2(j)个0,即0x800
2.1.2 字数据大小
字长即为平常所说的32位字长机器或者64位字长机器,指明指针数据的标称大小,一个字长为w位的机器,虚拟地址的范围为0~2^w-1,程序最多访问2^w个字节。
有些数据类型的确切字节数依赖于程序是如何被编译的。程序员应力图是他们的程序在不同的机器和编译器上可移植,可移植的一个方面就是使程序对不同数据类型的确切大小不敏感。
2.1.3 寻址和字节顺序
在几乎所有的机器上,多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中最小的地址。例如一个类型为int的变量x的地址为0x100,那么(假设数据类型int为32位表示)x的4个字节将被存储在内存的0x100,0x101,0x102,0x103位置。
排列表示一个对象的字节有两个通用的规则,一个是最高有效字节在最前面的方式称为大端法,一个是最低有效字节在最前面的方式称为小端法。大多数intel兼容机都只用小端模式。
对于大多数应用程序员来说,其机器使用的字节顺序是完全不可见的。但是当小端法机器产生的数据被发送到大端法机器或者反过来时,接受程序会发现,字里的字节成了反序的。因此网络应用程序的编写必须遵守已建立的关于字节顺序的规则。
2.1.4 表示字符串
常见的对字符编码的是ASCII字符码,在使用ASCII码作为字符码的任何系统上都将得到相同的结果,与字节顺序和字大小规则无关,因此文本数据比二进制数据具有更强的平台独立性。
ASCII字符集适合于编码英语文档,对于一些其他国家的特殊字符就没有办法,因此有了统一字符集Unicode,使用32位表示字符,这样每个字符要占用4个字节,不过有一些替代编码将常见的字符使用1个字节,特别是UTF-8将每个字符编码为1个字节序列,这也就意味着所有的ASCII字节序列用ASCII码表示和用UTF-8表示是一样的。
2.1.5 表示代码
不同的机器类型使用不同的且不兼容的指令和编码方式,二进制代码很少能在不同机器和操作系统组合之间移植。
2.1.6 布尔代数简介
布尔将逻辑值(true,false)编码为二进制值(1,0)。
2.1.7 c语言中的位级运算
c语言中&(与),|(或),~(取反),^(异或)
c中表达式~0x41,二进制表达式~[0100 0001],二进制结果[1011 1110],十六进制结果0xBE(先转成二进制数计算结果再转回来)
2.1.8 c语言中的逻辑运算
c语言中逻辑运算符&&(与),||(或),!(非)
逻辑运算与位级运算的两个主要区别:一是逻辑运算返回结果只有1或0两种结果;二是逻辑运算对第一个参数求值就能确定表达式结果就不会对第二个参数求值,如a&&5/a就不会造成被0除
x=0x66,y=0x39,x&y=1100110&111001=0100000=0x20,x&&y=1100110&&111001=0000001=0x01
2.1.9 c语言中的移位运算
机器支持两种形式的右移:逻辑右移和算术右移
逻辑右移在左端补k个0,算术右移在左端补k个最高有效位的值。
x=0xC3,先转为二进制数11000011,x>>2(逻辑右移)=00110000,x>>2(算术右移)=11110000
x=0x75,先转为二进制数01110101,x>>2(逻辑右移)=00011101,x>>2(算术右移)=00011101