#Pragma Pack(n)内存分配

简介: #Pragma Pack主要是用在字节对齐方面,为什么要对齐呢?因为计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。

@[TOC]

Pragma Pack主要是用在字节对齐方面,为什么要对齐呢?

因为计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。

#Pragma Pack (n)指定对齐的字节数

1、基本数据类型所占内存大小

#include<stdio.h>
char           a;
short          b;
int            c;
float          d;
double         e; 
long           f;
unsigned char  g;
unsigned short h; 
unsigned int   i; 
int main()
{
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t\n",sizeof(a),sizeof(b),sizeof(c),sizeof(d),sizeof(e),sizeof(f),sizeof(g),sizeof(h),sizeof(i));
return 0;
}

在这里插入图片描述

2、对齐规则

1)未指定#pragma pack时,系统默认的对齐模数4字节(32位机,X86系统等)。
2)指定#pragma pack 对齐模数时,实际取pack 对齐模数和默认的最小值。
3)结构体里面static变量,因为静态变量的存放位置与结构体实例的存储地址无关,是单独存放在静态数据区的,因此用siezof计算其大小时没有将静态成员所占的空间计算进来。

3、举例说明

默认按四个字节对齐,如果不足4个字节,就按4各字节算。如果大于4个字节,就不用管,是多少字节就是多少字节。

#include<stdio.h>
typedef struct student
{
  char           a;  //默认4个字节对齐,char           是1个字节,以4字节对齐,按4个字节处理
  short          b;  //默认4个字节对齐,short          是2个字节,以4字节对齐,按4个字节处理
  int            c;  //默认4个字节对齐,int            是4个字节,以4字节对齐,按4个字节处理
  float          d;  //默认4个字节对齐,float          是4个字节,以4字节对齐,按4个字节处理
  double         e;  //默认4个字节对齐,double         是8个字节,以4字节对齐,按8个字节处理
  long           f;  //默认4个字节对齐,long           是4个字节,以4字节对齐,按4个字节处理
  unsigned char  g;  //默认4个字节对齐,unsigned char  是1个字节,以4字节对齐,按4个字节处理
  unsigned short h;  //默认4个字节对齐,unsigned short 是2个字节,以4字节对齐,按4个字节处理
  unsigned int   i;  //默认4个字节对齐,unsigned int   是4个字节,以4字节对齐,按4个字节处理
}student;
int main()
{
  printf("%d",sizeof(student));
  return 0;
}

假如我们不使用字节对齐,那么这个结构体就是1+2+4+4+8+4+1+2+4=28个字节,但是我们实际打印确是40个字节。
在这里插入图片描述
这是因为编译器默认以4个字节对齐,不足4个字节(比如short和char),按4个字节处理。大于等于4个字节的就不用管。(比如double是8个字节,就按8个字节算)。
但是在实际工程中,如果我们是读取一块一块的数据,这些数据都是连在一起的,比如bmp图片,前14个字节是文件信息头,紧接着是40个字节的图像信息头。如果我们不用结构体对齐操作的话。那就乱了套了,数据就读取失败。
所以我们要在结构体前加上#Pragma Pack(1),以一个字节对齐,使用完后要加#pragma pack(),释放内存对齐。为啥要以一个字节对齐呢?是因为一般的数据类型都是大于等于1个字节的。这样的话就会按照数据类型原有的的分配。就不会错位了。

具体请看

#include<stdio.h>
#pragma pack(1) 
typedef struct student
{
  char           a;  //设置1个字节对齐,char           是1个字节,以1字节对齐,按1个字节处理
  short          b;  //设置1个字节对齐,short          是2个字节,以1字节对齐,按2个字节处理
  int            c;  //设置1个字节对齐,int            是4个字节,以1字节对齐,按4个字节处理
  float          d;  //设置1个字节对齐,float          是4个字节,以1字节对齐,按4个字节处理
  double         e;  //设置1个字节对齐,double         是8个字节,以1字节对齐,按8个字节处理
  long           f;  //设置1个字节对齐,long           是4个字节,以1字节对齐,按4个字节处理
  unsigned char  g;  //设置1个字节对齐,unsigned char  是1个字节,以1字节对齐,按1个字节处理
  unsigned short h;  //设置1个字节对齐,unsigned short 是2个字节,以1字节对齐,按2个字节处理
  unsigned int   i;  //设置1个字节对齐,unsigned int   是4个字节,以1字节对齐,按4个字节处理
}student;
#pragma pack()
int main()
{
  printf("%d",sizeof(student));
  return 0;
}

这回就按照每个变量的类型给出实际的结果了,1+2+4+4+8+4+1+2+4=30
在这里插入图片描述
怎么样,现在知道内存对齐#pragma pack(n) 的用法了吧。

关注微信公众号:[<font=red>果果小师弟],获取更多精彩内容!

相关文章
|
12月前
|
消息中间件 网络协议 C#
C#使用Socket实现分布式事件总线,不依赖第三方MQ
`CodeWF.EventBus.Socket` 是一个轻量级的、基于Socket的分布式事件总线系统,旨在简化分布式架构中的事件通信。它允许进程之间通过发布/订阅模式进行通信,无需依赖外部消息队列服务。
C#使用Socket实现分布式事件总线,不依赖第三方MQ
|
7月前
|
负载均衡 安全 容灾
虚拟专线设备端配置指南 (无影 x iKuai)
本文档主要介绍AL88系列设备的环境准备、上网配置及插件配置。环境准备包括个人电脑、网线、设备及互联网连接;上网配置涵盖设备拆箱检查、通电接线、浏览器登录管理后台和内外网设置;插件配置则通过高级应用完成无影虚拟专线的绑定。
|
消息中间件 负载均衡 Java
消息队列 MQ使用问题之负载不均衡是什么导致的
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
Vue3+Vite+Js项目搭建之二:vite.config.js 构建
Vue3+Vite+Js项目搭建之二:vite.config.js 构建
374 1
|
数据安全/隐私保护
解决使用SourceTree下载GitLab服务器上的代码每次都需要输入密码问题
解决使用SourceTree下载GitLab服务器上的代码每次都需要输入密码问题
371 2
|
调度 UED Python
探索Python中的异步编程:从回调到async/await
本文将深入探讨Python中的异步编程,从最初的回调函数到现代的async/await语法。通过比较不同的异步编程方法,读者将了解它们的优缺点,并学习如何在项目中选择合适的方式来提高性能和可维护性。
|
算法 调度 数据库
【C++20 新特性 Calendar (C++20) − Time zone (C++20)】时间的艺术与科学: C++中的现代日期和时区处理
【C++20 新特性 Calendar (C++20) − Time zone (C++20)】时间的艺术与科学: C++中的现代日期和时区处理
588 3
|
Oracle jenkins Java
【Jenkins】使用java -jar jenkins.war --httpPort=XXXX启动Jenkins报错【解决方案】
【Jenkins】使用java -jar jenkins.war --httpPort=XXXX启动Jenkins报错【解决方案】
|
Java 编译器
【Java探索之旅】解密Java中的类型转换与类型提升
【Java探索之旅】解密Java中的类型转换与类型提升
245 0
|
前端开发 JavaScript 容器
你知道css中的object-fit的用法吗?
你知道css中的object-fit的用法吗?
382 0