结构体位域定义与#Pragam pack()

简介: 结构体位域定义与#Pragam pack()

位域

定义结构体时,有时会使用位域来定义变量,这样能够最大限度的节省内存空间。我们知道,一个字节占8位。如不使用位域定义,我们一般定义变量为:

U8 addr;

这个变量占8位字节。取值范围为0-255,可如果我们定义的变量,取值范围达不到255的级别,那么8位的字节中许多bit位就浪费掉了。不要小看这几个bit位,在嵌入式系统中,尤其是硬件资源紧张的情况下,每一个bit都应该能发挥自己的作用。这就需要我们灵活使用位域来定义。

典型例子

一个典型的例子是定义开关标志量。开关量一般取值为01,因此仅用1个bit位表示即可。这种情况可以使用位域来定义。如下

struct Flag_ST {
U8 flag1 :1;
U8 flag2 :1;
U8 flag3 :1;
U8 reserved : 5; }

按照上面的定义,三个flag变量每个都占用一位的空间,整个结构体也只占用一个字节的长度。

字节对齐 #Pragam pack()

定义位域之前,需要了解字节对齐。可使用#Pragam pack(n)来实现。括号中的n代表n个字节对齐。举个例子,

假设
U4型占4字节,也就是32
U2型占2字节,也就是16
U1型占1字节,也就是8
那么定义结构体

struct Flag_ST {
U4 flag1 ;
U2 flag2 ;
U1 flag3 ;}

则整个结构体我们计算是占用7个字节长度。但实际计算sizeof时会发现占用8个字节。

这是因为系统默认4字节对齐,而U1U2由于加起来不够4个字节,因此被放在了一个4字节单位中,8个字节中的最后一个字节被空了出来,也就浪费了。
如果我们在定义这个结构体之前加上

#Pragam pack(1)

让系统1字节对齐,那么计算sizeof时我们会发现该结构体占用7字节内存,不会造成内存的浪费。

相关文章
|
8月前
|
存储 编译器 Linux
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
|
8月前
|
存储 编译器 Linux
匿名结构体类型、结构体的自引用、结构体的内存对齐以及结构体传参
匿名结构体类型、结构体的自引用、结构体的内存对齐以及结构体传参
|
8月前
|
存储 程序员 C++
定义和使用结构体变量
定义和使用结构体变量
86 1
|
7月前
|
存储 编译器 C语言
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)一
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)一
66 2
|
7月前
|
编译器 Linux C语言
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)二
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)二
60 1
|
8月前
|
存储 C#
C#.Net筑基-类型系统②常见类型--结构体类型Struct
本文介绍了C#中的结构体(struct)是一种用户自定义的值类型,适用于定义简单数据结构。结构体可以有构造函数,能定义字段、属性和方法,但不能有终结器或继承其他类。它们在栈上分配,参数传递为值传递,但在类成员或包含引用类型字段时例外。文章还提到了`readonly struct`和`ref struct`,前者要求所有字段为只读,后者强制结构体存储在栈上,适用于高性能场景,如Span和ReadOnlySpan。
|
8月前
|
存储
结构体和结构体指针的区别
结构体和结构体指针的区别
256 1
|
8月前
|
存储 安全 算法
定义指针
定义指针
54 1
|
8月前
|
存储 C++
[C++] 结构体Struct类型和变量定义
[C++] 结构体Struct类型和变量定义
145 0
|
C语言
【C语言】结构体 -- 结构体的声明 -- 定义和初始化 -- 成员的访问 -- 结构体传参
【C语言】结构体 -- 结构体的声明 -- 定义和初始化 -- 成员的访问 -- 结构体传参