结构体字节对齐问题

为什么结构体所占内存大于所有成员之和 首先由几个反常现象说起 第一个反常现象: typedef struct{ int a; double b; char c; } Test; Test 结构体的所占内存大小应该为int 的4字节+double 的8字节+char 的1字节=13字节,但反常的地方就是Test所占用的内存并不是13字节,而是24字节,整整翻了接近一倍 printf("%lu\n",Test); 第二个反常现象: typedef struct{ int a; char c; double b; } Test; 阅读详情

结构体字节对齐

      在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排列, 而不是简单地顺序排列,这就是内存对齐。

      内存对齐的原因:

      1)某些平台只能在特定的地址处访问特定类型的数据;

      2)提高存取数据的速度。比如有的平台每次都是从偶地址处读取数据,对于一个int型的变量,若从偶地址单元处存放,则只需一个读取周期即可读取该变量;但是若从奇地址单元处存放,则需要2个读取周期读取该变量。

       win32平台下的微软C编译器对齐策略:

      1)结构体变量的首地址能够被其最宽数据类型成员的大小整除。编译器在为结构体变量开辟空间时,首先找到结构体中最宽的数据类型,然后寻找内存地址能被该数据类型大小整除的位置,这个位置作为结构体变量的首地址。而将最宽数据类型的大小作为对齐标准。

      2)结构体每个成员相对结构体首地址的偏移量(offset)都是每个成员本身大小的整数倍,如有需要会在成员之间填充字节。编译器在为结构体成员开辟空 间时,首先检查预开辟空间的地址相对于结构体首地址的偏移量是否为该成员大小的整数倍,若是,则存放该成员;若不是,则填充若干字节,以达到整数倍的要 求。

      3)结构体变量所占空间的大小必定是最宽数据类型大小的整数倍。如有需要会在最后一个成员末尾填充若干字节使得所占空间大小是最宽数据类型大小的整数倍。

 

下面看一下sizeof在计算结构体大小的时候具体是怎样计算的

1.test1   空结构体

typedef struct  node
{
     
}S;

则sizeof(S)=1;或sizeof(S)=0;

在C++中占1字节,而在C中占0字节。

2.test2

typedef struct  node1
{
     int  a;
     char  b;
     short  c;
}S1;

则sizeof(S1)=8。这是因为结构体node1中最长的数据类型是int,占4个字节,因此以4字节对齐,则该结构体在内存中存放方式为

|--------int--------|   4字节

|char|----|--short-|   4字节

总共占8字节

3.test3

typedef struct  node2
{
     char  a;
     int  b;
     short  c;
}S2;

 则siezof(S3)=12.最长数据类型为int,占4个字节。因此以4字节对齐,其在内存空间存放方式如下:

|char|----|----|----|  4字节

|--------int--------|  4字节

|--short--|----|----|  4字节

总共占12个字节

4.test4  含有静态数据成员  

typedef struct  node3
{
     int  a;
     short  b;
     static  int  c;
}S3;

则sizeof(S3)=8.这里结构体中包含静态数据成员,而静态数据成员的存放位置与结构体实例的存储地址无关(注意只有在C++中结构体中才能含有静态数据成员,而C中结构体中是不允许含有静态数据成员的)。其在内存中存储方式如下:

|--------int--------|   4字节

|--short-|----|----|    4字节

而变量c是单独存放在静态数据区的,因此用siezof计算其大小时没有将c所占的空间计算进来。

5.test5  结构体中含有结构体

typedef struct  node4
{
     bool  a;
     S1 s1;
     short  b;
}S4;

则sizeof(S4)=16。是因为s1占8字节,而s1中最长数据类型为int,占4个字节,bool类型1个字节,short占2字节,因此以4字节对齐,则存储方式为

|-------bool--------|  4字节

|-------s1----------|  8字节

|-------short-------|  4字节

6.test6

typedef struct  node5
{
     bool  a;
     S1 s1;
     double  b;
     int  c;
}S5;

则sizeof(S5)=32。是因为s1占8字节,而s1中最长数据类型为int,占4字节,而double占8字节,因此以8字节对齐,则存放方式为:

|--------bool--------|    8字节

|---------s1---------|    8字节

|--------double------|    8字节

|----int----|---------|     8字节 

7.test7 

若在程序中使用了#pragma pack(n)命令强制以n字节对齐时,默认情况下n为8.

则比较n和结构体中最长数据类型所占的字节大小,取两者中小的一个作为对齐标准。

若需取消强制对齐方式,则可用命令#pragma pack()

如果在程序开头使用命令#pragma pack(4),对于下面的结构体

typedef struct  node5
{
     bool  a;
     S1 s1;
     double  b;
     int  c;
}S5;

则sizeof(S5)=24.因为强制以4字节对齐,而S5中最长数据类型为double,占8字节,因此以4字节对齐。在内存中存放方式为:

  |-----------a--------|   4字节

  |--------s1----------|   4字节

  |--------s1----------|   4字节

  |--------b-----------|   4字节

  |--------b-----------|   4字节

  |---------c----------|    4字节

总结一下,在计算sizeof时主要注意一下几点:

1)若为空结构体,则只占1个字节的单元

2)若结构体中所有数据类型都相同,则其所占空间为 成员数据类型长度×成员个数

若结构体中数据类型不同,则取最长数据类型成员所占的空间为对齐标准,数据成员包含另一个结构体变量t的话,则取t中最 长数据类型与其他数据成员比较,取最长的作为对齐标准,但是t存放时看做一个单位存放,只需看其他成员即可。

3)若使用了#pragma pack(n)命令强制对齐标准,则取n和结构体中最长数据类型占的字节数两者之中的小者作为对齐标准。

 

另外除了结构体中存在对齐之外,普通的变量存储也存在字节对齐的情况,即自身对齐。编译器规定:普通变量的存储首地址必须能被该变量的数据类型宽度整除。

测试程序:

?
/*测试sizeof运算符  2011.10.1*/
 
#include <iostream>
using  namespace  std;
//#pragma pack(4)    //设置4字节对齐 
//#pragma pack()     //取消4字节对齐 
 
typedef  struct  node
{
     
}S;
 
typedef  struct  node1
{
     int  a;
     char  b;
     short  c;
}S1;
 
typedef  struct  node2
{
     char  a;
     int  b;
     short  c;
}S2;
 
typedef  struct  node3
{
     int  a;
     short  b;
     static  int  c;
}S3;
 
typedef  struct  node4
{
     bool  a;
     S1 s1;
     short  b;
}S4;
 
typedef  struct  node5
{
     bool  a;
     S1 s1;
     double  b;
     int  c;
}S5;
 
 
 
int  main( int  argc,  char  *argv[])
{
     cout<< sizeof ( char )<< " " << sizeof ( short )<< " " << sizeof ( int )<< " " << sizeof ( float )<< " " << sizeof ( double )<<endl;
     S s;
     S1 s1;
     S2 s2;
     S3 s3;
     S4 s4;
     S5 s5;
     cout<< sizeof (S3)<<endl;
     cout<< sizeof (s)<< " " << sizeof (s1)<< " " << sizeof (s2)<< " " << sizeof (s3)<< " " << sizeof (s4)<< " " << sizeof (s5)<<endl;
     return  0;
}
结构体占用内存大小如何确定?-->结构体字节对齐 | C语言 结构体字节对齐 阅读详情

相关推荐

MSP430之共用体中结构体字节对齐问题

MSP430之共用体中结构体字节对齐问题 先上代码: 我所用的平台的字节对齐默认是2字节,下面////////之间的变量定义为7个字节,为了保证2字节对齐,Power变量就会自动扩展一个字节,但是变量类型又是一个字节,所以发生了字节偏移的情况。 typedef union _PARARW{ struct{ UINT8 Name[24]; /////////////////////////...

洋洋洋的博客 796

结构体字节对齐

在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排列, 而不是简单地顺序排列,这就是内存对齐。 内存对齐的原因: 1)某些平台只能在特...

weixin_30399821的博客 366

基于强化学习的工业SCR脱硝系统控制算法设计与实现

本文提出了一种基于强化学习的工业SCR脱硝系统智能控制方法。针对SCR系统存在的非线性、大滞后和多变量耦合等控制难点,研究采用混合建模方法构建了精度在5%以内的系统模型,并设计了专门的强化学习环境。该方法通过定义合理的动作空间和状态空间,结合物理约束设计损失函数,利用深度强化学习算法优化氨喷射控制策略。相比传统PID控制,该智能控制器能更好地适应烟气参数波动,实现NOx排放的稳定控制,为工业环保设施提供了更优的自动化解决方案。

huanghm88的专栏 1456

关于字节对齐的总结

(1) 例题1 修饰的是 struct test ,是一个类型,本身大小是24 ,但依照16对齐时,后面空着,故补齐 形成2个16.且最小对齐方式是16。__attribute__((__n__)) ,强制按照该值来对齐 __attribute__ ((aligned (4)))(2) 例题2 修饰的是test 应该修饰的是一个变量。可以被该数据类型所占字节数整除,char可以放在任意位置,int存放在。使用时可以直接访问stu1.a//当成成员函数的调用。((aligned(x)))定义的是。

QuanQuanYuanXin的博客 973

Python实战:5分钟搞定VCF文件中每个样本的SNP统计(附bcftools安装指南)

本文介绍了三种高效统计VCF文件中每个样本SNP数量的Python方法,包括原生解析、结合bcftools的推荐方案以及使用PyVCF3专业库。特别推荐bcftools结合Python的方法,适用于中大型VCF文件,显著提升处理效率。文章还提供了bcftools安装指南和进阶统计技巧,帮助生物信息学分析人员快速完成SNP统计任务。

weixin_30555125的博客 494

【UE5_蓝图】实时音频采集与动态WAV文件保存实战指南

本文详细介绍了在UE5中使用蓝图实现实时音频采集与动态WAV文件保存的完整流程。从插件配置、录音框架搭建到动态文件名生成和音频参数优化,提供了实用技巧和常见问题解决方案,特别适合需要快速实现音频采集功能的开发者。

weixin_29009669的博客 407

结构体所占内存

结构体所占的内存由结构体里的成员决定 int型占4字节 char型占1字节 float型占4字节 double型占8字节 指针*占4字节 但在结构体中所占的内存并不是所有成员所占字节之和,而是有一定规律 以程序为例: 此时结构体的内存就是一个字节 加一个char型的成员 结果为两个字节 如果再加入一个int型成员 结果就是8个字节 如果将成员顺序调

qq_37655087的博客 1685

Jenkins离线安装保姆级教程:从下载.war包到SVN+Maven项目一键部署(附避坑脚本)

本文详细介绍了Jenkins离线安装的全流程,包括.war包下载、SVN+Maven项目配置及自动化部署。特别针对内网环境提供解决方案,涵盖插件管理、开发工具链配置、构建触发器和SSH部署等关键步骤,帮助企业在网络隔离环境下实现高效持续集成。

weixin_30096975的博客 374

QT进行通信,定义结构体时需要字节对齐的问题

系统1:ThinkPad T570、Windows10、QT5.12.2(Qt Creater 4.8.2) 在与其他设备进行UDP通信时,我一般会定义通信协议包结构,如下图所示是一个简单的例子: ,然后在程序中我会定义一个结构体,如下所示: struct PACKET_PC1_PC2 { quint32 m_nFrameHead;//0xFFAA低位在前,高位在...

weixin_43935474的博客 8630

有限元缺陷:剪切锁死

有限元缺陷:剪切锁死

wsxww11的博客 5186

Shopee App加密算法逆向实战:从libshpssdk.so到x-sap-ri的生成机制

本文详细解析了Shopee App核心加密参数x-sap-ri的生成机制。通过逆向分析libshpssdk.so动态库,揭示了其采用9套算法动态切换的复杂签名逻辑,并分享了从抓包定位、Frida动态调试到Unidbg模拟执行的全过程实战经验,为移动应用安全研究提供了完整的技术路径。

weixin_29323551的博客 1327

C - 结构体字节对齐问题

C - 结构体字节对齐问题           关于C语言中的结构体字节对齐问题,在《C与指针》一书中提到,但是似乎没有说清楚,还是我理解不完全?所以,根据书上和网上资料,总结一些关于C语言中的结构体字节对齐的知识。这里的讨论和代码,都在VS2010下,GCC不太熟悉就不说了;-(   (1)什么是字节对齐[1] 对齐规则:         结构体中一个变量占用 n 个字节,则该变量的

DayDreamingBoy的专栏 3354

Cursor自动生成测试用例

或者把你已有的规则直接复制粘贴到这个文档内(这里我用的是Markdown格式和CSV格式的测试用例生成规则,可以同时生成Markdown和CSV格式的测试用例)。在AI对话框这里,我们可以看到Cursor会逐步来帮我们生成测试用例,先分析识别需求文档,然后生成测试用例,最后会进行质量检查,确保生成的用例符合规范。生成的Markdown格式,可直接导入Xmind,生成思维导图,对应到具体的功能模块看具体的测试点,逻辑会更直观一些。(1)选中规则文档和需求文档:@你的测试用例规则文档@你的需求文档。

十二测试录 2431

sizeof 与结构体大小及结构体对齐问题, 字节对齐

遇到了这样的情况 有如下结构体 struct ST_1 {       char a;       double b;       char c; };   1. 写入文件 ST_1 st; st.a = 'a'; st.b = 123.4; st.c = 'b'; fwrite(&st, sizeof(ST_1), 1, file);   2. 从文件中读出来

cay22的专栏 1480

使用 MATLAB/Simulink 进行锂电池SOC估算和等效电路建模

本文介绍了使用MATLAB/Simulink进行锂电池SOC估算与等效电路建模的方法。首先阐述了SOC估算和等效电路模型的背景及重要性,然后详细讲解了系统结构设计的主要组成部分,包括电池模块、SOC估算模块(采用卡尔曼滤波器算法)和等效电路模型等。文章重点分步说明了建模过程:从创建Simulink项目、搭建电池模块,到实现SOC估算算法(提供示例代码),构建等效电路模型(Thevenin模型示例),添加传感器模块,最后设置仿真参数。通过仿真运行分析关键指标(SOC估算误差、电压偏差等)来评估模型性能,为锂电

xiaoheshang_123的博客 263

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C语言结构体字节对齐问题

C/C++结构体字节对齐问题1 前言2 举例3.其他 1 前言 对于结构体字节对齐问题,我发现我一直有一个误区,正是这个误区,给我带来了很大困扰,今天突然顿悟,在此记录一下,希望能帮到大家。 2 举例 #include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)0)->f)) struct AD { int a; char b[13]; double c;}; #pragma pack(push) #prag

stone322的博客 767

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

结构体字节对齐的问题

最近在使用udp传输结构体的时候,发现了一个问题:结构体的实际大小和预想的并不一样,例子如下: struct msg { int index; int length; char id; int start; }; 如上所示的结构体中,预估大小为4 * 3 + 1 = 13 字节,但是实际上使用sizeof函数得到结果是16。通过wireshark抓包发现实际上存在一个字节对齐的问题:...

ty的博客 550

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

python结构体字节对齐_Python及字节对齐的问题

该结构大致如下:struct TestStruct{int data1;char data2;char data3;};对应的Python代码:import structs = struct.unpack("icc", buf) #buf是从网络接收的字节流结果却报“Unpack str size does not match format”错。很明显是C++ struct产生的size和Pyth...

weixin_39836530的博客 772

C++中结构体的字节对齐问题

  前不久,在C++程序中碰到一个有关结构体字节对齐的问题。一。问题描述在程序中,定义了一个结构体,如下:typedef struct{   char name[33];   int ID;   int  age;} PERSON;声明了一个该结构体的数组:PERSON peo[30];当从结构体中取出ID字段给一个int类型的局部变量赋值时,却出现异常.比如结构体中的字段都已经有

roger007的专栏 3663

结构体中字节对齐的问题

在一个16位的机器,以下结构由于边界对齐浪费了多少空间() 1 2 3 4 5 struct{      char a;      int b;      char c; }  2   4    6   8 16位机器,cha

xinruzhishuizw的博客 710

结构体变量 存到24C02中 读出来不对 (结构体成员变量 字节对齐问题)

本想把 结构体 变量数据 保存 到24C02中, 再读取保存数据,验证保存是否成功。开始没加 #pragma pack (x) 对齐关键字,结果反复调试都是失败只有部分数据存进去了。若将成员变量一个一个存,再一个一个读就没问题。在单步调试发现成员变量的地址不连续。豁然开朗 原来字节 对齐问题,编译器默认是4字节对齐,所以就导致了成员变量地址不连续。成员变量中有1、2、4字节的公约数是1, 所以加 #pragma pack (1) 1字节对齐就解决了结构体成员变量地址不连续问题,让其连续。 触摸屏校准

1094

windows和Linux之间socket传输结构体关于字节对齐产生的问题

这个是我在做转码机的时候发现的问题。这个转码机大致的思路是:将转码机上面的数据用结构体打包通过socket发送给Linux客户端。Linux客户端也是用结构体去接收。 发送的过程中出现了这样一个问题,就是发送的结构体数据中有不同字节的数据时,发生错误。 问题原因: 是因为windows和Linux平台上面结构体字节对齐的个数不同产生错误。 解决方法: 设置windows和Linux上面的

u012654882的专栏 2294

嵌入式开发过程中结构体字节对齐问题pragma pack(1)

一、引言 曾经刚入门嵌入式在开发一个应用时,用到了自定义结构体,底层嵌入式单片机运行该结构体没问题,但是在Qt开发应用软件对接协议时,一直通不过,仔细分析才发现是QT这边的结构体字节并没有按照单字节对齐,后来在定义结构体时,增加了宏定义,强迫该结构体按照单字节对齐的方式进行编译,即可解决问题。 二、问题描述 假设有一个结构体,包含5字节头,一个字长度的负载,和一个字节的尾,例如: typ...

健忘16的博客 2285
上一篇: 如何理解奇偶校验只能发现数据代码中奇数位出错的情况
下一篇: 资源分配图化简法
coding1994
博客等级 码龄11年 149粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值