背景知识
结构体中的冒号表示位域。
位域出现的原因是由于某些信息的存储表示只需要几个bit位就可以表示而不需要一个完整的字节,同时也是为了节省存储空间和方便处理。
实际应用
测试电脑为小段模式:
typedef union
{
char u;
struct
{
unsigned char a :1;
unsigned char b :1;
unsigned char c :1;
unsigned char d :5;
} ST;
}UN;
int main()
{
UN a;
printf("sizeof(a):%d\n", sizeof(a));
a.u = 0;
a.ST.a = 1;
a.ST.b = 2;
a.ST.c = 3;
a.ST.d = 4;
printf("a.u:0x%x, a.ST.a:%d, a.ST.b:%d, a.ST.c:%d, a.ST.d:%d\n", a.u, a.ST.a, a.ST.b, a.ST.c, a.ST.d);
}
以上打印的结果为多少,电脑为小段模式:
编译的时候代码已经给出警告, a.ST.b = 2;a.ST.c = 3;这个两句话赋值有问题,但是我们不管,直接跑下去。
结果是a.ST.b = 0;a.ST.c = 1;
因为只有分配的只有1位的空间,而2,和3需要2位才能够存储下去。因此,这里的赋值会被截断,高位被截断只留下地位,结果就是0,1。而元素a,d都有足够的空间来存放赋值的内容,因此没有这个问题。
因此最终内存上的值是,二进制,0010 0101,十六进制,0x25.
至于这里为什么是 0010 0101而不是,1010 0100 呢
可以看下面的例子:
char x[] = {0x78, 0x56, 0x34, 0x12};
for (int i = 0;i < 4; i++)
{
printf("addr x[%d]:%x\n", i, &x[i]);
}
printf("x:%x\n", *(int*)(&x));
这里是以字节存储为例,高字节在高地址,低字节在底地址。
但是从上面的位域操作我们是否可以总结:
小端是分配内存地址时从低地址开始,但是变量的数值是从高地址往低地址读,这句话同样适用于一个字节里面的位的存储