理论部分 转自 太空
1.位域的概念
C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”(bit field)。
(1)位段成员的类型必须指定为unsigned或int类型;
(2)若某一位段要从另一个字开始存放,用:0长度为0的空位段,作用就是使下一个位段从下一个存储单位(视不同编译系统而异)开始存放;
(3)一个位段必须存储在同一存储单元中,不能跨两个单元;(这句有问题,存储单元就是1字节,应该改为“一个位段必须存储在同一变量中,不能跨两个变量”)
(4)可以定义无名字段例如":2";
(5)位段的长度不能大于存储单元的长度,也不能定义位段数组; (这句有问题,存储单元就是1字节,应该改为位段的长度不能大于变量的长度)
(6)位段可以用整形格式符输出;
(7)位段可以在数值表达式中引用,它会被系统自动地转换成整形数。
2.Little-endian systems的内存布局特点
Motorola的PowerPC系列CPU采用的Big-endian, Intel的X86系列CPU采用的是Little-endian。
Little-endian的特点是高高低低,即高位地址存放最高有效字节,低位地址存放最低有效字节;而Big-endian正好相反。
面试宝典的一道题:
typedef struct bitstruct{ int b1:5; int :2; int b2:2; }bitstruct; void main(){ bitstruct b; memcpy(&b,"EMC EXAMINATION",sizeof(b)); printf("%d,%d\n", b.b1, b.b2); }
程序开头不是定义了bitstruct是个位域结构么,b1,b2分别是只占5位和2位的成员.这个结构中成员占据了9位,需要2个字节,考虑到字节对齐的原因,实际占了4个字节,但这不重要,关键是b1,b2只占据了2个字节.因此,我们只关心memcpy(&b,"EMC EXAMINATION",sizeof(b)); 中,'E'和'M'两个字符带来的影响. 'E'的ASCII码是69,对应二进制是01000101. 'M'的ASCII码是77,对应二进制是01001101. b1占据的正好是'E'的低5位,即00101,对应的十进制正好是5.然后6,7位对应bitstruct的第二个未命名的成员,再是'E'的第8位和'M'的最低位,组成b2,所以b2的值是10.因此最高位是1,所以是负数的补码,对应的负数是-2.
关于b2:原题中b2根本就没有跨变量长度,因为变量长度是32位(int)。
存储单元就是1字节。
数据总线长度32位 => 一次性读取长度:32位
存储单元 和 总线长度 无关。
至于位段的条件(3)一个位段必须存储在同一变量中,不能跨两个变量 验证了一下:
结构体改成:
typedef struct bitstruct{
int b1:1;
int :30;
int b2:2;
}bitstruct;
结果:b2=01。证明了:一个位段必须存储在同一变量中,不能跨两个变量