7.7.1位段。
在struct中,对于int或unsigned int类型。使用 int i:5;的形式,确定该成员位数大小。
1.大小不能超过该位段类型大小。位段在内存中具体储存形式由具体编译器决定。
2.当前位段不能放在一个存储单元时(该存储单元特指位段类型大小,int,unsigned int也就是4字节),会将当前存储单元剩余空间闲置,从下一个存储单元开始。
struct A{
int a:2;
int b: 29;
int c:1
};
sizeof(A)是4字节,如果b位段是30位,就是8字节。如果b位段是32位,就是12字节。
位段在同一存储单元里的紧凑的,可以定义无名字段,是为了分隔空位,不使用所对应的位。
A t; t.a=1; t.c=1; cout<<t.a<<t.c; 结果是1,-1.因为存储的是01,1转换成int时,位扩展,01扩展为00000000000000000001,1被当成负数,扩展为1111111111111111.
7.7.2如何快速得到一个数的7倍
移位操作,(X<<3)-X
7.7.3 用位操作实现求平均数
(x&y+(x^y>>1));都为1的不用除2,单独为1的除2
这种方法可以保证不溢出。
引申:求一个数的绝对值。
对于整数x,x>>31。x为正数,结果是0x00000000,x为负数,结果是0xffffffff。
y=x>>31;
x的绝对值等于 x^y-y;
x^0x00000000不变。
x^0xffffffff是按位取反(包括符号位),再加1,相当于进行反码操做+1.
7.7.4注意补码。
32位机器。取值范围0-4294927695. int的是-2147483647~2147483647
7.7.5判断一个整数的1的个数
使用x&(x-1);
while(x) count++; x&=x-1;
x-1按位来看,是使最右为1的位变成0;
注意0x1u,指的是16位无符号数1.
7.7.6 不用sizeof判断系统是32位还是16位。
对unsigned int a=~0判断。0取反后得到最大值。
16位表示最大值65535,如果a>65536.则是32位的。
7.7.7大端和小端
小端模式cpu对操作数的存储从低字节向高字节存。小端模式先存34,再存12.
大端模式cpu从高字节向低字节存。如0x1234,大端模式先存12,再存34.
x86为小端模式,单片机一般为大端模式。
注意 0的ASCII码是48,A是65,a是97
判断模式可以使用截断的方法,如用short int a=0x1234;char b=a;b==0x12就是大端,是0x34就是小端。
7.78 n位2进制数,有多少个数中不存两个相邻的1.
1.斐波拉契数列,a[n]=a[n-1]+a[n-2],a[1]=a[2]=初值。
int F(int i){
if(i==1)
return 2;
if(i==2)
return 3;
return F(i-1)+F(i-2);
}
2.递推
int F(int i){
if(i==1)
return 2;
if(i==2)
return 3;
int n1=2;int n2=3;
for(int n=n1+n2;i>3;i--)
n1=n2;
n2=n;
n=n1+n2;
}
7.7.9关于位运算的知识
这个后续补充,比较重要