共用體與位域 --20240310

lethe1203發表於2024-03-10
共用體
共用體(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

相關文章