共用体与位域 --20240310
共用体
共用体(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