Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
C语言
结构体
结构体大小 你算对了吗
1.00
发布于 2021-11-30 11:50:39 浏览:995
订阅该版
[tocm] C 语言中 struct 声明创建一个数据类型(结构体),能将不同类型的对象聚合到一个对象中,用名字来引用结构体的各个组成部分。结构体的所有组成部分都存放在一段连续的内存中。 如果创建一个结构体,其实际占用的内存空间大小是多少呢?示例代码如下: ```c struct S { int i; char c; int j; }; ``` 要正确计算结构体大小,首先需要了解数据对齐的原理。 ### 数据对齐 许多计算机系统对基本的数据类型的合法地址做了一些限制。要求某种类型对象的地址必须是某个值(通常为2、4、8)的倍数。这种对齐限制简化了形成处理器和内存系统之间接口的硬件设计。 **对齐原则**:任何占用 K 字节空间大小的基本对象,其地址必须是 K 的倍数。 那么, char 类型数据存储地址 必须是 1 的倍数。short 类型数据存储的地址为 2 的倍数,以此类推。 确保每种数据类型都是按照指定方式来组织和分配,即每种类型的数据都满足它的对齐限制,就可以保证实施对齐。 对于包含结构体的代码,编译器可能需要在字段的分配中插入间隙,以保证每个结构成员都满足它的对齐要求。而结构体本身对它的起始地址也有一些对齐要求。 由此,编译器可能需要在结构体成员内存的分配中插入间隙,保证每个结构成员都满足它的对齐要求。或者需要在结构体的末尾加入填充,从而使得结构体数组中的每个元素都会满足它的对齐要求。 ### 结构体大小计算 **情形一** 结构体中间插入间隙,上述代码: ```c struct S { int i; char c; int j; }; ``` 如果编译器按照最小 9 字节分配,是不可能满足成员 i 和 j 的 4 字节对齐要求的。此时,编译器会在成员 c 和 j 之间插入一个 3 字节的间隙。结果 j 的偏移量为 8,而整个结构体的大小 为 12。 **情形二** 另外一个示例如下,其大小是多少呢? ```c struct S2 { int i; int j; char c; }; ``` 要正确计算这个结构体的大小,需要这样考虑:创建这个结构体的数组,每个数组元素都会满足它的对齐要求。 如果给这个结构体分配 9 个字节。考虑结构体数组 `struct s2 a[4]`,就不能满足数组 a 的每个元素的对齐要求。假设数组的起始地址为 x,则每个元素的地址分别为 x、x+9、x+18、x+27,有三个元素不满足对齐原则。 由此,编译器会为结构 s2 分配 12 个字节,最后三个字节是补充的空间(浪费的空间),即**在结构体的末尾增加填充**。 **情形三** 结构体成员是另外一个结构体时,示例如下: ```c struct sta { int i; int j; char c; }; struct stb { int i; char c; int j; char cc; struct sta tmp; }; ``` 结构体 srb 的大小是多少呢? 要计算这种类型的结构体,只需要把其中的结构体成员当成一个整体即可。 先忽略 成员 tmp,结构体 stb 的大小为 16 字节(中间和末尾均需要填充间隙);结构体 sta 的大小为 12 字节。从而可以计算得出,结构体 stb 的实际大小为 16 + 12 = 28 字节。 **情形四** 使用编译指令,示例代码如下: ```c #pragma pack(1) struct S3 { int i; int j; char c; } #pragma pack() ``` 注意编译指令 **pragma pack** 的主要作用就是改变编译器的内存对齐方式。在不使用这条指令的情况下,编译器采取默认方式对齐。 此处的两条编译预处理指令,使得在这之间定义的结构体按照 1 字节方式对齐。在本例中,使用这两条指令的效果是,**编译器不会在结构体尾部填充空间了**。 这个结构体的大小为 9 字节。
4
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
zppsky16
公众号【一起学嵌入式】,RTOS、Linux、C/C++
文章
7
回答
5
被采纳
0
关注TA
发私信
相关文章
1
netdev.h头文件不能被其他c文件包含,否则报错
2
有关多sensor设备的module定义结构体自调用的疑惑
3
rtt消息队列收发的结构体数据不一样
4
同类型的结构体怎么在keil运行的时候大小不一样?
5
RT-Thread内存和字符串相关函数与C语言自带的内存和字符串相关函数冲突问题
6
嵌入式RT-thread中初始化线程函数中(void *)entry的意义何在
7
cJSON parse 失败,请问怎么解决?
8
请教一个C语言顺序表的问题,不知道有没有大佬帮吗解答
9
小白请教,关于头文件引用,、、哪些场景需要引用它们?
10
使用中断有warn。。。。。。。。。。。
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
YZRD
2
篇文章
4
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部