当前位置:网站首页>比你老师详细系列————结构体
比你老师详细系列————结构体
2022-07-23 03:58:00 【双一周学八天】
目录
一、结构体的声明
1.声明
struct S
{
//想要存储的数据类型,如:
int i;
char c;
};
这里只是声明了一个结构体类型,相当于蓝图,还无法使用,我们还需要申请一个变量,就像是用蓝图建好了房子。
struct S s1;这就是申请变量的形式,struct S就是这里的数据类型,所以struct也叫自定义类型。与之对应的还有枚举和联合,接下来我都会慢慢讲解。
创建变量还有另外一种方法,在声明结构体时同时创建一个变量:
struct S
{
int i;
char c;
}s1;
这个s1就是我们声明的变量,这是后内存才划分了一部分内存空间给s1。
2.不完全声明
结构体的声明还有一种不太常用的写法:不完全声明
struct
{
int i;
char c;
};
在申明结构体类型的时候我不申明类型名称。这样申明带来的结果就是这个结构体类型只能使用一次声明变量,所以它适用的场景也只有在值使用一次结构体的情况。
上面举出的这个例子是无方法使用这个类型的,只有像下面这样才可以:
struct
{
int i;
char c;
}s1,s[10];
这样我就在声明的同时创建了两个变量,包括一个结构体数组。
下面提出一个思考:
struct
{
int i;
char c;
}x;
struct
{
int i;
char c;
}*p;
p=&x;
p=&x这一个动作是否合法
答案是否定的,应为在声明第二个结构体类型的时候,第一个实质上已经不存在了,这两个结构体类型不是同一个,所以这样x的地址无法存入p。
3.结构体的自引用
这里的自引用的,‘自’指的是在这个结构体里继续引用这个类型的结构体
错误的自引用:
struct S
{
int i;
char c;
struct S s;
};
这样引用有一个很大的问题,S里面套用了S,那第二个S里面继续套用一个S,这样就形成了一个无限套娃,编译器是无法满足这样近乎无限的内存需求的。
正确的自引用:
struct S
{
int i;
char c;
struct S *next;
};
用指针的形式就可以避免以上的情况了。
二、结构体的内存对齐
结构体的声明就讲完了,让我们来讨论一下结构体内存大小吧。

来预测一下S1和S2类型的变量分别会占据多少内存。
并不是6个字节,而且题目两个所占字节数还不相同。

这一结果的原因就是内存对齐。
内存对齐
S1的结构体内存布局其实如下

图中的数字为偏移量,0就是结构体被分配内存的开始。可能你会不理解,要是如下图分配的话不是就节省的很多的空间吗

内存对齐的原因之一————性能:
电脑访问数据可能是四个四个字节的访问,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访 问。

在这里我们需要访问两次,才能将i的数据读取完整。
原因之二——————平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特 定类型的数据,否则抛出硬件异常。
内存对齐计算规则
1. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
struct S
{
char c1;
int i;
char c2;
}s1;
以这个为例 :
1.c1 字节数为1,比默认对齐数8相比较小,从0开始,占据了0
2.i字节数为4,与默认对齐数相比较小,所以i的对齐数为4,那么i要从4的整数倍开始,因此从4开始,占据了4~7
3.c2字节数为1,相比默认对齐数较小,其对齐数为1,因此从1的整数倍开始,占据了8.
4.到目前为止结构体占了9个字节,但结构体大小要是最大对齐数的整数倍(默认值不参与比较),这里的最大值为4,因此该结构体占据了12个字节,为0~11.

边栏推荐
- Kingbasees SQL language reference manual of Jincang database (8. Function (4))
- MD5加密解密网站测试,MD5加密还安全吗?
- Data middle office, Bi business interview (III): how to choose the right interviewees
- 实现城市治理一网统管,必须这 4 个关键技术
- Time series dataset: power transformer dataset (etdataset)
- Redis安装
- Nine charts overview the cycle law of encryption Market
- Self organization is the two-way rush of managers and members
- Use the x2mindspire tool of mindstudio to convert training scripts
- 智慧园区的核心本质是什么?
猜你喜欢
![[c#] IEnumerable可枚举类型接口分析yield](/img/08/8c346ce257b4adc0bea80bf05b6f52.png)
[c#] IEnumerable可枚举类型接口分析yield

EasyCVR新版本(v2.5.0)目录分级功能如何使用?

RTC 性能自动化工具在内存优化场景下的实践

How to add an operator in ONEFLOW

多线程中的「lost wake up 问题」| 为什么wait()和notify()需要搭配synchonized关键字使用?

Redis transaction, lock mechanism, seckill

mysql三表查询问题

MySQL three table query problem

MySQL queries all table names and column information of the database through SQL
![[basics of C language] 14 file, declaration and format input and output](/img/92/e7a9ec9e39349757f78aed4f5a622a.jpg)
[basics of C language] 14 file, declaration and format input and output
随机推荐
Redis installation
Data middle office, Bi business interview (III): how to choose the right interviewees
32-spark的分区算子介绍、广播变量和累加器
Special training - linked list
适合拼多多小商家配件的一些思路跟技巧
How to add an operator in ONEFLOW
Redis transaction - detailed implementation process of seckill case simulation
Advantages and disadvantages of RDB and AOF
Redis token record user login design solution?
QT error: error c2039 "value": not a member of "`global namespace"
客户至上 | 国产BI领跑者,思迈特软件完成C轮融资
EasyCVR平台升级到最新版本v2.5.0,如何同步mysql数据库?
[C language foundation] 16 variable array (array length can be extended)
How to improve browsing security? Teach you to set up a secure browser trust site
Undo log日志详解
金仓数据库 KingbaseES SQL 语言参考手册 (8. 函数(六))
[vscode] the current working directory is not the current folder /pathlib print CWD path error
C language -- several classic exercises of C language
Read write barrier in memory barrier -- concurrency problem
Online English learning system based on s2sh+mysql