当前位置:网站首页 > 技术博客 > 正文

结构体中的联合体怎么分配内存



目录

1 结构体

1.1 结构体的声明

1.2 结构体的成员类型

1.3 结构体变量的定义和初始化

1.4 结构体成员的访问

1.5 结构体的自引用

1.6 结构体内存对齐

1.7 结构体传参

1.8 结构体实现位段

1.8.1 位段

1.8.2 位段的内存分配 

2 联合体/共用体


结构体是一些值的集合,这些值可以称为是“成员变量”。

结构体中的每个成员可以是不同类型的。

  • 常规声明方式 
 
   

【使用示例】 

 
   
  • 特殊声明:匿名结构体 

 在声明结构体时,省略类型名字

 
   

 匿名结构体只能在声明时定义变量。由于匿名结构体没有类型名字,因此他们不能在其他地方被引用或重新定义

【使用示例】

 
   

因此,匿名结构体用常用于临时使用结构体或某些特定场景下。 

但是匿名结构体可以用typedef关键字重新定义名字

 
   

结构体成员可以是变量、数组、指针,或者其他结构体

【结构体变量的定义方式】 

  1. 声明类型的同时定义变量
  2. 在使用时定义 
 
   

 【结构体变量的初始化方式】

  1. 声明类型同时定义变量并赋初值
  2. 使用时定义变量并赋初值
 
   
  •  结构体嵌套的初始化

结构体嵌套声明也包含上面说的两种变量定义及初始化方式。

 
   
  • 注意:在C语言中,没有对结构体类型使用typedef关键字重命名时,struct关键字不能省略!

没有 typedef:如果没有使用 typedef 创建别名,每次使用结构体变量时必须加上 struct 关键字。

使用 typedef:通过 typedef 创建别名后,就可以直接使用别名来定义结构体变量,无需每次都写 struct 关键字。

 
   

【通过 . 点操作符访问成员】

结构体变量名.结构体成员变量名

 
   

 【通过指针访问成员】

当某个函数传入参数为指向某个结构体的指针,就可以使用指针访问成员。

 
   

在C语言中,结构体的自引用(self-referential structure)是指一个结构体类型在其定义中包含一个指向自身类型的指针。这种结构设计允许创建链表、树等动态数据结构,因为它可以让每个结构体实例指向另一个相同类型的结构体实例。

 【使用示例】

 
   

 【注意点】:自引用的时候不要定义为匿名结构体。

匿名结构体在定义时并没有给结构体本身分配一个名称,因此无法在结构体定义中引用到该类型。这意味着无法在结构体内部声明一个指向它自身的指针,因为没有办法表明这个类型是什么。

【内存对齐存在的原因】

  1. 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
  2. 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

因此,在设计结构体的时候,既要满足对齐,又要节省空间。

【结构体内存对齐规则

  1. 第一个成员在与结构体变量偏移量为0的地址处
  2. 其他成员变量对齐到对齐数的整数倍的地址处
  3. 结构体总大小为最大对齐数的整数倍
  4. 如果嵌套了结构体,嵌套结构体对齐到自己的最大对齐数的整数倍处

 其中:

对齐数=编译器默认的对齐数该成员大小 较小值

VS中默认的值为8;Linux中没有默认对齐数,对齐数就是成员自身的大小

注意!:对齐数用于对齐,元素占内存大小还是取决于自身类型大小。

【示例】

 
   

 

 

【修改默认对齐数】

结构在对齐方式不合适的时候,我们可以自己更改默认对齐数。

使用 #pragma预处理指令 修改。一般设置为2^n,不要设置为奇数

 
   
 
   

结构体传参也分为传值和传址。但是传值时形参只是实参的一份临时拷贝,如果结构体很大,这种方式会浪费空间,所以使用传址方式更好。 (函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。)

1.8.1 位段

位段的声明和结构是类似的,有两个不同:

  1. 位段的成员必须是整型家族成员,如: int、unsigned int 或signed int 。
  2. 位段的成员名后边有一个冒号和一个数字。

1.8.2 位段的内存分配 

位段的内存分配遵循以下3点:

  1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
  2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

 

【内存分配示例】

 
   

联合体也是一种特殊的自定义类型。这种类型定义的变量包含一系列的成员,特点是这些成员共用同一块空间

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。

 
   

【联合体大小计算】

  1.  联合的大小至少是最大成员的大小。
  2. 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
 
  
  

                            

版权声明


相关文章:

  • tiny c compiler 源码2025-07-25 10:01:05
  • 适配器设计模式的基本原理2025-07-25 10:01:05
  • hashmap和hashtable和hashset2025-07-25 10:01:05
  • linux中user是什么意思2025-07-25 10:01:05
  • 软件测试面试怎么说2025-07-25 10:01:05
  • mysql函数大全以及举例2025-07-25 10:01:05
  • 径向基函数神经网络2025-07-25 10:01:05
  • 虚拟机软件叫什么2025-07-25 10:01:05
  • 单片机delay延时计算公式2025-07-25 10:01:05
  • orm框架的基本原理2025-07-25 10:01:05