共用體
共用體(Union)是一種特殊的資料型別,它允許在同一個記憶體位置儲存不同的資料型別。
共用體的所有成員共享同一塊記憶體空間,因此同一時間只能儲存其中一個成員的值。
共用體的定義和結構體類似,使用關鍵字union,後面跟著成員列表。每個成員可以是不同的資料型別,但共用體的所有成員都共享同一塊記憶體空間,大小取決於最大的成員
共用體使用舉例demo:
#include <string.h> union Data { int i; float f; char str[20]; }; int main() { union Data data; data.i = 10; printf("data.i = %d \n", data.i); printf("sizeof(data) = %ld \n", sizeof(data)); data.f = 20; printf("data.f = %f \n", data.f); printf("sizeof(data) = %ld \n", sizeof(data)); strcpy(data.str, "Hello"); printf("data.str: %s\n", data.str); printf("sizeof(data) = %ld \n", sizeof(data)); return 0; } // 執行結果 data.i = 10 sizeof(data) = 20 data.f = 20.000000 sizeof(data) = 20 data.str: Hello sizeof(data) = 20
位域
暫存器的一個bit位在儲存時並不需要佔用一個完整的位元組,只需要一個bit,用0和1表示足以,也就是用一個二進位。正是基於這種考慮,C語言又提供了一種資料結構,叫做“位域”或“位段”。
位域的儲存:
位域的儲存遵循結構體記憶體對齊的原則,舉個例子:
#include <stdio.h> struct pack { int a:2; int b:4; int c:6; } a; int main(void) { printf("sizeof(a) = %d \n", sizeof(a)); return 0; } // 執行結果 sizeof(a) = 4
a、b、c成員所佔的位長之和在一個儲存單元(此處為int型別所佔的位元組數)內,即4個位元組內,所以struct pack型別的變數所佔的位元組長度為4個位元組(實際a、b、c一共佔用12bit,還有20bit空間為保留的空白)。此處要將記憶體對齊到 4 個位元組(int型別所佔的位元組數),以便提高存取效率。
共用體和位域結合使用
暫存器操作時,共用體和位域結合使用十分方便,如下
#include <stdio.h> union GPA_REG0 { int resval; struct { int bit0: 1; int bit1: 1; int bit2: 1; int bit3: 1; int bit4: 1; int bit5: 1; int bit6: 1; int bit7: 1; int bit8: 1; int bit9: 1; int bit10: 1; int bit11: 1; int bit12: 1; int bit13: 1; int bit14: 1; int bit15: 1; } fields; }; union GPA_REG0 gpa_reg0; void gpa_reg0_modify(union GPA_REG0 *addr) addr->fields.bit0 = 1; addr->fields.bit1 = 1; addr->fields.bit2 = 1; addr->fields.bit3 = 1; addr->fields.bit4 = 1; addr->fields.bit5 = 1; addr->fields.bit6 = 1; addr->fields.bit7 = 1; addr->fields.bit8 = 1; addr->fields.bit9 = 1; addr->fields.bit10 = 1; addr->fields.bit11 = 1; addr->fields.bit12 = 1; addr->fields.bit13 = 1; addr->fields.bit14 = 1; addr->fields.bit15 = 0; } int main() { printf("gpa_reg0.resval = 0x%lx, sizeof(gpa_reg0) = %d \n", gpa_reg0.resval, sizeof(gpa_reg0)); gpa_reg0_modify(&gpa_reg0); printf("gpa_reg0.resval = 0x%lx, sizeof(gpa_reg0) = %d \n", gpa_reg0.resval, sizeof(gpa_reg0)); } // 執行結果 gpa_reg0.resval = 0x0, sizeof(gpa_reg0) = 4 gpa_reg0.resval = 0x7fff, sizeof(gpa_reg0) = 4