1.共用體(Union):
共用體是一種特殊的資料型別,允許您在相同的記憶體位置存盤不同的資料型別,您可以定義一個帶有多成員的共用體,但是任何時候只能有一個成員帶有值,共用體提供了一種使用相同的記憶體位置的有效方式,
為了定義共用體,您必須使用 union 陳述句,方式與定義結構類似,
例子:
union Data {
int i;
float f;
char str[20];
} data;
這意味著一個變數(相同的記憶體位置)可以存盤多個多種型別的資料,您可以根據需要在一個共用體內使用任何內置的或者用戶自定義的資料型別,共用體的占用的記憶體大小由最大的變數決定---這個例子里面就是字串(char str[20]),占用20個位元組記憶體,
為了訪問共用體的成員,我們使用成員訪問運算子(.), 但是和結構體不一樣,由于共用體本質上是一個記憶體位置,所以會導致在同一時間里只能有一個值占用記憶體位置,
比如:
data.i = 10;
data.f = 220.5;
strcpy( data.str, "C Programming");
printf( "data.i : %d\n", data.i);
printf( "data.f : %f\n", data.f);
printf("data.str : %s\n", data.str);
列印(printf)這個三個值,前兩個值都會損壞,因為記憶體位置被賦給了str.
但是假如是:
data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 220.5;
printf( "data.f : %f\n", data.f);
strcpy( data.str, "C Programming");
printf( "data.str : %s\n", data.str);
每次記憶體被占用之后都列印了出來,然后又重新賦值,所以不會造成損壞,
共用體作用:
節省記憶體,有兩個很長的資料結構,不會同時使用,比如一個表示老師,一個表示學生,如果要統計教師和學生的情況用結構體的話就有點浪費了!用共用體的話,只占用最長的那個資料結構所占用的空間,就足夠了!
共用體應用場景:
通信中的資料包會用到共用體:因為不知道對方會發一個什么包過來,用共用體的話就很簡單了,定義幾種格式的包,收到包之后就可以直接根據包的格式取出資料,
2.位域 Bit field(深入):
假設我們需要一個結構體只儲存一個固定長度的值(比如說 1,0 這種來代表true/false --- 0001只需要一個bit)的,如果正常去定義,需要兩個 int (每個4位元組 Byte,一共 8 Byte),C 語言提供了一種更好的利用記憶體空間的方式,如果您在結構內使用這樣的變數,您可以定義變數的寬度來告訴編譯器,您將只使用這些位元組Byte,
定義例子:
struct {
unsigned int widthValidated : 1;
unsigned int heightValidated : 1;
} status;
如上,status 變數將占用 4 個位元組(byte)的記憶體空間,但是只有 2 位(bit)被用來存盤值,意思就是說這兩個成員共用了一個int的記憶體空間(都是同型別),
如果您用了 32 個變數,每一個變數寬度為 1 位,那么 status 結構將使用 4 個位元組,但只要您再多用一個變數,如果使用了 33 個變數,那么它將分配記憶體的下一段來存盤第 33 個變數,這個時候就開始使用 8 個位元組,
Age.age = 7;
printf( "Age.age : %d\n", Age.age );
Age.age = 8; // 二進制表示為 1000 有四位,超出
printf( "Age.age : %d\n", Age.age );
output :
Age.age : 7
Age.age : 0
這個結果還會伴隨著警告,
sub:(來自上章)
1.一個位域存盤在同一個位元組中,如一個位元組所剩空間不夠存放另一位域時,則會從下一單元起存放該位域,也可以有意使某位域從下一單元開始,
2.由于位域不允許跨兩個位元組,因此位域的長度不能大于一個位元組的長度,也就是說不能超過8位二進位,如果最大長度大于計算機的整數字長,一些編譯器可能會允許域的記憶體重疊,另外一些編譯器可能會把大于一個域的部分存盤在下一個字中,
3.位域可以是無名位域,這時它只用來作填充或調整位置,無名的位域是不能使用的.
4.位域在本質上就是一種結構型別,不過其成員是按二進位分配的,
5.結構體變數的首地址能夠被其最寬基本型別成員的大小所整除,
6.結構體每個成員相對于結構體首地址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充位元組(internal adding),即結構體成員的末地址減去結構體首地址(第一個結構體成員的首地址)得到的偏移量都要是對應成員大小的整數倍,
7.
超出范圍并不是直接丟棄,而是保留對應的 3 位的值,
比如 8 是 00001000,按照位域,對應 3 位的值是 000,所以列印結果是 0;
但是 9 是 00001001,按照位域,對應 3 位的值是 001,所以列印結果是 1;
同理 10 是 00001010,按照位域,對應 3 位的值是 010,所以列印結果是 2;
參考:
https://www.runoob.com/cprogramming/c-unions.html
https://www.runoob.com/cprogramming/c-bit-fields.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/61744.html
標籤:C
上一篇:排兵布陣
