位域
#include <stdio.h> #include <stdlib.h> //位字段:嵌入式的物联网设备开发,需要节约内存,可以使用位字段,用来限定某个结构如变量的二进制位 struct dateE{ unsigned int day; // day只有1-31的取值,无需用到4个字节,浪费了内存 2^5=32 5个二进制位就足够了 unsigned int month; // month只有1-12的取值,无需用到4个字节,浪费了内存 2^4=32 4个二进制位就足够了 unsigned int year; // 只有0000-9999 的取值,无需用到4个字节,浪费了内存 2^14=16384 14个二进制位就足够了 }; struct date{ //相比上面的定义,date结构体只有4个字节,大大节约了内存空间 unsigned int day : 5; // day只有1-31的取值,无需用到4个字节,浪费了内存 2^5=32 5个二进制位就足够了 unsigned int month : 4; // month只有1-12的取值,无需用到4个字节,浪费了内存 2^4=32 4个二进制位就足够了 unsigned int year :14; // 只有0000-9999 的取值,无需用到4个字节,浪费了内存 2^14=16384 14个二进制位就足够了 }; //为什么是4个字节呢?因为考虑到内存字节对齐的问题 // 占用5位 1111 1 000 1个字节,不足补0 // 占用4位 1111 0000 1个字节,不足补0 // 占用14位 1111 1111 | 1111 11 00 | 两个字节合并到一起,2个字节,不足补0 // 在结构体中:CPU是按照字节寻址的,字节是CPU访问的最小单位,总共4个字节 //在限定位数的结构体——位域中,CPU是按位运算寻址的,不是按字节 void main1(){ printf("%d\n", sizeof(struct dateE)); //12 printf("%d\n", sizeof(struct date)); //4 结构体对齐 }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //位字段的注意事项 //如果两个字符之和小于8位,会自动填充一个字节,通位操作操作位字段 //1(1位) 11111(5位) 00 1代表其占用的位,一个字节存储两个位域变量ch1,ch2 //int占用4个字节,虽然只有一位使用,后面的会默认为0,且无法使用这些0 //结构体前面的char类型为了和int字节对齐,后面补0,也对应四个字节,总共8个字节 //1 11111 00 00000000 00000000 00000000 4个字节 //1 00000000 00000000 00000000 00000000 4个字节 struct data{ unsigned char ch1 : 1; //结构体限定了位数,越界会溢出 unsigned char ch2 : 2; // unsigned char ch3 : 10; 位字段不能超过类型的大小8个位 // unsigned char ch4 : 0; 位字段不能为0 int num : 1; }; void main(){ printf("%d\n", sizeof(struct data)); //8个字节 struct data data1; data1.ch1 =2; data1.num =2; printf("%d\n",data1.ch1); //0 2的二进制位10,而ch1只能处理以为,溢出,输出0 printf("%d\n",data1.num); //0 虽然num占用4个字节,但是后面的0无法利用, 2的二进制位10,而ch1只能处理以为,溢出,输出0 //取地址 printf("%p\n",data1); //可以去结构体的地址 printf("%p\n",data1.ch1); //错误,不可以取位域的地址 //位域是通过位运算来实现,无法取出位域的地址(一个字节存储两个位域变量ch1,ch2) }