前言

大家好,我是小昭,因为在不同硬件平台数据传输时,遇到关于字节对齐的问题,索性就做了总结,以下是我对字节对齐的理解和小结,如有疑问请联系我。

目录

  • 结构体变量占用空间不同

  • 为什么要字节对齐?(内存对齐)

  • 字节对齐的规则

结构体变量占用空间不同

typedef struct data_type1{char a[2];short b;int c;
} Data_type1;
typedef struct data_type2{short a;int b;  char c[2];
} Data_type2;

先看看上面两个结构体,如果有定义成对应的变量,它俩占内存空间是多少 ?使用sizeof()占用多少空间,都是8个字节大小,答案不是。

Data_type1和Data_type2结构体里的成员变量类型相同,两者的所占的空间应该是相同的,但是事实却不是如此。

经过实践编写代码输出的结果,却是这样的。

/*ubuntu gcc环境 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>#define debug_printf(value) printf(#value " ---==> %d\n", value)
#define debug_struct_member_offset(struct, member) (((char *)(&(((struct *)0)->member))) - ((char *)0))
typedef struct data_type1{char a[2];short b;int c;
} Data_type1;
typedef struct data_type2{short a;int b;  char c[2];
} Data_type2;
int main(int argc, char** argv){int a,b,c;a = debug_struct_member_offset(Data_type1,a);b = debug_struct_member_offset(Data_type1,b);c = debug_struct_member_offset(Data_type1,c);debug_printf(sizeof(Data_type1));debug_printf(a);debug_printf(b);debug_printf(c);a = debug_struct_member_offset(Data_type2,a);b = debug_struct_member_offset(Data_type2,b);c = debug_struct_member_offset(Data_type2,c);debug_printf(sizeof(Data_type2));debug_printf(a);debug_printf(b);debug_printf(c);
}

Data_type1和Data_type2的类型变量占用的大小分别是8和12.

为什么会出现这样的结果?

因为编译器对数据进行了优化,做了字节对齐操作,可以增加内存的使用率和数据高效得传输。

什么是字节对齐?

现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但是实际的计算机系统对基本类型数据在内存中存放的位置有限制,计算机并非逐个字节读取,而是以2、4、8的倍数字节块读取内存,它们会要求这些数据的首地址的值是某个数是k(通常是4或8)的倍数 ,这就是所谓的内存对齐。大白话就是,各种数据类型都要一定的规则进行排列,而不是一个接一个的排放,这就是对齐。

为什么需要字节对齐?

1、减少cpu访问变量的次数,cpu可以更快的读取数据

2、合理的使用字节对齐,可以节省内存的大小。

3、减少 cpu 访问数据的出错性(有些 cpu 必须内存对齐,否则指针访问会出错),不同硬件平台进行数据通信,数据对齐可能会不一致,需要加入伪指令进行操作,防止灾难性性bug。

字节对齐的规则

规则一:结构体变量的首地址能够被字节对齐的大小整除(gcc 缺省字节对齐大小是4)。

规则二:结构体的每个成员相对首地址的偏移是成员类型大小的整数倍。(成员自身对齐)

规则三:结构体变量的总大小是结构体里最大的成员的整数倍。(结构体本身对齐)

计算结构体变量的字节大小,以上面的例子说明

Data_type1结构体变量类型,大概这样存放的。

计算字节大小可以不关心规则一,可以被忽略。看规则二,第二个成员b的偏移是2是short大小(2)的整数倍,第三个成员c的偏移量是4是int的大小的整数倍。看规则三,总的大小是8字节,是int大小的整数倍,c成员后面不需要填内容。

Data_type1结构体变量类型

看规则二,第二个成员b的偏移是2不是int大小(4)的整数倍,成员a后面补2个字节才能被4整除,第三个成员c的偏移量是8是char的大小的整数倍。看规则三,总的大小是10字节,不是是int大小(4)的整数倍,成员c补上内容(2),直到能被4整除,所以总大小是12个字节。

在设计数据结构的时候,可以看出合理调整成员的排序,可以节省内存使用。但是需要在空间上和可读性进行权衡。

思考,结构体类型,被实体化后,占用的字节大小:

typedef struct data_type3{char a;char b;  char c;
} Data_type3;
typedef struct data_type4{char a;char b[2];  //char c;
} Data_type4;

答案都是3.

有什么办法可以对字节对齐进行干预?

1、使用#prama park(n)伪指令,会对前面规则二和规则三进行干预,大白话,成员本身字节对齐和结构体本身对齐大小不能大于n,只能小,如果能理解这这句话,问题就不大了,直接看例子吧。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>#define debug_printf(value) printf(#value " ---==> %d\n", value)
#define struct_member_offset(struct, member) (((char *)(&(((struct *)0)->member))) - ((char *)0))#pragma pack(4)  //4字节对齐开始 对齐大小只能比4小,不能大
typedef struct
{uint32_t b;    /*double 8字节对齐,这里正常是要补4字节内容,但是编译器这里规定最多只能4个字节对齐,如果是short就按2个字节对齐,只能小不拿大*/double   f;
} test_t;
#pragma pack()//字节对齐结束
int main()
{int b = struct_member_offset(test_t, b);int f = struct_member_offset(test_t, f);debug_printf(sizeof(test_t));debug_printf(b);debug_printf(f);return 0;
}

运行结果:

注释#pragma pack(4) 占用空间是16.

2、使用__attribute((aligned(n))),操作结构体时,这里可以看成是对规则三进行干预,对结构体本身对齐。

typedef struct
{uint8_t  a;    // 偏移地址uint16_t b;    // 偏移地址
}__attribute((packed)) test_t1; //按实际空间
typedef struct
{uint8_t  a;    // 偏移地址uint16_t b;    // 前补1 偏移地址
}__attribute((aligned(4))) test_t2;
typedef struct
{uint8_t  a;    // 偏移地址uint16_t b;    //前补1 偏移地址
}__attribute((aligned(8))) test_t3;
typedef struct
{uint8_t  a;    // 偏移地址uint16_t b;    //前补1 偏移地址
}__attribute((aligned(16))) test_t4;
//#pragma pack()
int main()
{debug_printf(sizeof(test_t1));debug_printf(sizeof(test_t2));debug_printf(sizeof(test_t3));debug_printf(sizeof(test_t4));return 0;
}

运行结果

留个坑:


typedef struct data_type1{char a[2];short b;int c;
} Data_type1;
typedef struct data_type2{short a;Data_type1 b; //Tips: 这部分按里面最大成员大小对齐 所以要补. 至于补多少……char c[2];
} Data_type2;

sizeof(Data_type2)是多少?

答案:16

以上是结果,都是经过我测试验证成功,如有疑问,请麻烦联系我。我是小昭!

字节对齐看这篇就够了(内存对齐)相关推荐

  1. uiautomation遍历windows所有窗口_万字长文!滑动窗口看这篇就够了!

    大家好,我是小浩.今天是小浩算法 "365刷题计划" 滑动窗口系列 - 整合篇.之前给大家讲解过一些滑动窗口的题目,但未作系统整理. 所以我就出了这个整合合集,整合工作中除了保留原 ...

  2. 史上最全!用Pandas读取CSV,看这篇就够了

    导读:pandas.read_csv接口用于读取CSV格式的数据文件,由于CSV文件使用非常频繁,功能强大,参数众多,因此在这里专门做详细介绍. 作者:李庆辉 来源:大数据DT(ID:hzdashuj ...

  3. Android原生TabLayout使用全解析,看这篇就够了

    前言 为什么会有这篇文章呢,是因为之前关于TabLayout的使用陆陆续续也写了好几篇了,感觉比较分散,且不成体系,写这篇文章的目的就是希望能把各种效果的实现一次性讲齐,所以也有了标题的「看这篇就够了 ...

  4. 【超全汇总】学习数据结构与算法,计算机基础知识,看这篇就够了【ZT帅地】2020-3-7

    https://blog.csdn.net/m0_37907797/article/details/104029002 由于文章有点多,并且发的文章也不是一个系列一个系列发的,不过我的文章大部分都是围 ...

  5. 一文详解JavaBean 看这篇就够了

    一文详解JavaBean 看这篇就够了 JavaBean的历史渊源 JavaBean的定义(通俗版) JavaBean应用 < jsp:useBean > < jsp:getProp ...

  6. React入门看这篇就够了

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 很多值得了解的细节. 原文:React入门看这篇就够了 作者:Random Fundebug经授权转载,版权归原作者所 ...

  7. .NET Core实战项目之CMS 第五章 入门篇-Dapper的快速入门看这篇就够了

    写在前面 上篇文章我们讲了如在在实际项目开发中使用Git来进行代码的版本控制,当然介绍的都是比较常用的功能.今天我再带着大家一起熟悉下一个ORM框架Dapper,实例代码的演示编写完成后我会通过Git ...

  8. .NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了

    本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新手朋友),但是转念一想不如来点猛的(考虑到急性子的朋友),让你通过本文的学习就能快速的入门ASP.NET Core.既 ...

  9. [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了

    园子里关于ASP.NET Core Web API的教程很多,但大多都是使用EF+Mysql或者EF+MSSQL的文章.甚至关于ASP.NET Core Web API中使用Dapper+Mysql组 ...

最新文章

  1. 程序员如何才能提高自己?通过一次重构代码讲解自己的感受【有代码比较】...
  2. Java学习笔记(43)——Java泛型
  3. 开启大数据时代谷歌三篇论文-Mapreduce
  4. hdu 4925 Apple Tree--2014 Multi-University Training Contest 6
  5. js面向对象之创建对象1
  6. 远程工具连接mysql备份_MySQL远程连接 备份还原
  7. [Swagger2]分组和接口注释及小结
  8. 19-数据持久化-Bind Mounting
  9. c语言综合编程,C语言编程入门——综合练习(一)
  10. binder.java 565_Android跨进程抛异常的原理的实现
  11. 动手实验:使用 jstat 摸清线上系统的JVM运行状况
  12. 字母和数字符号的ASCII码对照表转
  13. 西电计算机学院通知,西安电子科技大学计算机科学与技术学院关于发放2020级硕士研究生正式录取通知书的通知...
  14. 双十一全零售领域狂欢 请了明星代言商家真的能赚到钱吗?
  15. 只要你懂得人性,就不怕没钱赚!
  16. POJ 2671 Jimmy's Bad Day ★ (区间DP)
  17. node.js里的天龙八部
  18. 【最经典的79个】软件测试面试题(内含答案)都是可以提前准备的!
  19. 计算机设备耗材管理制度,关于国税局计算机耗材管理办法
  20. CMGAN: Conformer-based Metric GAN for Speech Enhancement

热门文章

  1. Ajax出现 beforeSend 和 complete 的方法失效问题(已解决)
  2. note3版本介绍,优劣总结
  3. Ubantu安装ttf和otf类型的字体
  4. ORCL数据库无监听程序解决方案
  5. Matlab数据处理(一):归一化处理
  6. 专访小米科技 VR 产品总监马杰思:VR 产品的迭代和技术瓶颈
  7. Shell脚本 一键重启
  8. Linux如何去设置TC参数
  9. RKMEDIA--RGA的使用
  10. 【已解决】使用pip安装包提示TLS证书错误解决办法