当前位置: 首页 > backend >正文

结构体详解

本文是小编巩固自身而作,如有错误,欢迎指出

1.结构体类型声明

在前文,已经讲述过相关问题,这里只进行简单解释

1.1结构声明

struct tag
{member-list;
}variable-list;

如果介绍一本书包括其价格,颜色

struct book
{char color[10];double price;
};

1.2结构体的创建和初始化 

看以下代码即可

#include <stdio.h>
struct Stu
{char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 
};
int main()
{//按照结构体成员的顺序初始化 struct Stu s = { "张三", 20, "男", "20230818001" };printf("name: %s\n", s.name);printf("age : %d\n", s.age);printf("sex : %s\n", s.sex);printf("id : %s\n", s.id);//按照指定的顺序初始化 struct Stu s2 = { .age = 18, .name = "lisi", .id = "20230818002", .sex = 
"⼥" };printf("name: %s\n", s2.name);printf("age : %d\n", s2.age);printf("sex : %s\n", s2.sex);printf("id : %s\n", s2.id);return 0;
}

2.结构体的内存对齐 

这部分内容将是本章重点讲述内容。

我们先看以下代码

struct S1
{char c1;int i;char c2;
};
int main()
{printf("%d\n", sizeof(struct S1));return 0;
}

 

其中struct的内存是怎么计算的呢,这就涉及结构体对齐, 下面详细介绍

内存对齐的原因

硬件访问效率:现代计算机硬件通常以特定的字节数(如2字节、4字节、8字节等)为单位来访问内存。如果数据存储的地址是对齐的,硬件可以更快地读取和写入数据,减少内存访问的次数和时间开销。

对齐规则

  1. 结构体的起始地址:结构体变量的起始地址必须是其最大成员类型大小的整数倍。例如,一个结构体包含一个char(1字节)和一个int(4字节),那么该结构体变量的起始地址必须是4的倍数。
  2. 成员变量的对齐:每个成员变量的存储地址必须是其自身类型大小的整数倍。例如,int类型的成员变量必须存储在4字节对齐的地址上。
  3. 结构体的总大小:结构体的总大小必须是其最大成员类型大小的整数倍。如果需要,编译器会在结构体的末尾填充额外的字节,以满足这个条件。

 

 

其排列可以如图所示

因为其最大对齐数为4,char类型就会浪费三个字节

3.结构体传参

通过上面的学习我们可以知道,结构体的的声明时是会出现内存较大的结构体的,如果直接使用结构体传参,就会开辟大量空间,所以我们可以用地址传参来减少空间的使用

struct S
{int data[1000];int num;
};//结构体地址传参 
void print2(struct S* ps)
{printf("%d\n", ps->num);
}
int main()
{struct S s = { {1,2,3,4}, 1000 };print2(&s); //传地址 return 0;
}

4.结构体实现位段 

4.1什么是位段

位段(bit field)是C语言和C++语言中的一种特殊数据结构,它允许在一个字节或多个字节内精确地分配和使用位。这在节省内存空间和直接操作硬件寄存器等场景中非常有用。

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

1. 位段的成员必须是 int、unsigned int 或signed int ,在C99中位段成员的类型也可以 选择其他类型。

2. 位段的成员名后边有⼀个冒号和⼀个数字。

#include<stdio.h>
struct A
{int _a:2;int _b:5;int _c:10;int _d:30;
};
int main()
{printf("%d\n", sizeof(struct A));return 0;
}

 

上述代码其实就是重新将bite位分配在32位环境下int型有32个bite位,其中前三项合起来不过32,共占4个字节

4.2 位段的内存分配

1. 位段的成员可以是 int unsigned int signed int 或者是 char 等类型

 2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的⽅式来开辟的。

 3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使⽤位段。

//⼀个例⼦ 
struct S
{char a:3;char b:4;char c:5;char d:4;
};
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
//空间是如何开辟的? 

现在我们来思考空间是怎么开辟的 

我们先看内存中的状况

 如图我们可以看到,内存中存放的是62 03 04,这是为什么呢,下面我们画图解释

 如图所示,当把每一个数从右向左放入内存,即可解释内存的存储

4.3位段使用的注意事项

位段的⼏个成员共有同⼀个字节,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位 置处是没有地址的。内存中每个字节分配⼀个地址,⼀个字节内部的bit位是没有地址的。

 所以不能对位段的成员使⽤&操作符,这样就不能使⽤scanf直接给位段的成员输⼊值,只能是先输⼊ 放在⼀个变量中,然后赋值给位段的成员。

 

struct A
{int _a : 2;int _b : 5;int _c : 10;int _d : 30;
};
int main()
{struct A sa = { 0 };scanf("%d", &sa._b);//这是错误的 //正确的⽰范 int b = 0;scanf("%d", &b);sa._b = b;return 0;
}

今天的分享就到这里了,后续会继续更新,感谢阅读!

http://www.xdnf.cn/news/544.html

相关文章:

  • (10)VTK C++开发示例 --- 点和线之间的距离
  • 【入门】数字之和为13的整数
  • Doris,新一代实时数仓核心基础设施
  • 数据防泄漏:企业信息安全的重要防线
  • Datawhale AI春训营学习
  • PHP框架在大规模分布式系统中的适用性如何?
  • deekseak 本地windows 10 部署步骤
  • ACM ICPC算法基础包括哪几类
  • Withholding Tax(预扣所得税)-前台操作 Part 1
  • System.in 详解
  • 【笔记】网络安全管理
  • 嵌入式单片机开发 - Keil MDK 编译与烧录程序
  • c++中的类有关概念
  • 精益数据分析(6/126):深入理解精益分析的核心要点
  • 五分钟学会如何基本使用JJWT!!!
  • Java虚拟机面试题:垃圾收集(下)
  • 3.基础开发工具
  • CLIP赋能视频分析:时空侧网络调优,行人属性识别效率革命
  • Java—— 常见API介绍 第二期
  • C++/Python实现RGB和HSI相互转换
  • Linux——firewalld防火墙(笔记)
  • 深度学习语音识别
  • bat脚本转换为EXE应用程序文件
  • 案例驱动的 IT 团队管理:创新与突破之路:第六章 组织进化:从案例沉淀到管理体系-6.1 案例库建设方法论-6.1.2案例分级与标签体系
  • OpenStack Yoga版安装笔记(23)Swift安装
  • QML中的3D功能--模型导入与修改
  • LRU Java实现
  • 五、小白如何用Pygame制作一款跑酷类游戏(主角跳跃和滑行动作的实现)
  • Linux | I.MX6ULL 使用 Yocto 文件系统开发 QT
  • 015-C语言字符函数和字符串函数