C學習筆記(6) 共用體,位域深入

2022-07-27 21:42:18 字數 3076 閱讀 7379

1.共用體(union):

共用體是一種特殊的資料型別,允許您在相同的記憶體位置儲存不同的資料型別。您可以定義乙個帶有多成員的共用體,但是任何時候只能有乙個成員帶有值。共用體提供了一種使用相同的記憶體位置的有效方式。

為了定義共用體,您必須使用union語句,方式與定義結構類似。

例子:union data 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 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 :7age.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;

引用:

c語言學習筆記 結構體位域

在學習結構體的時候遇到了位域這個概念,位域主要是為了節省記憶體空間,比如用乙個32位,4個位元組的int儲存乙個開關變數時,會造成空間浪費,於是乾脆就考慮在這個32劃分不同的區域來儲存資料,例如劃出1位存這個開關變數。struct tag unsigned int a unsigned int b ...

C語言學習筆記 C共用體

共用體是一種特殊的資料型別,允許在相同的記憶體位置儲存不同的資料型別。可以定義乙個帶有多成員的共用體,但是任何時候只能有乙個成員帶有值。共用體提供了一種使用相同的記憶體位置的有效方式。為了定義共用體,必須使用union語句,方式與定義結構類似。union語句定義了乙個新的資料型別,帶有多個成員。un...

C 學習筆記 6

通常,由於 c 風格字串與字串字面值具有相同的資料型別,而且都是以空字元 null 結束,因此可以把 c 風格字串用在任何可以使用字串字面值的地方 可以使用 c 風格字串對 string 物件進行初始化或賦值。string 型別的加法操作需要兩個運算元,可以使用 c 風格字串作為其中的乙個運算元,也...