#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)
}