linux中结构体对齐

C语言字节对齐与GNU __attribute__、__align()__选项使用说明 1、什么是字节对齐? 对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好等于它长度的整数倍,他就被称做自然对齐。比如在32位cpu下,假设一个int 型变量iNum的地址为0x00000004或0x00000008,那它就是自然对齐的;但是如果iNum的地址为 0x0000 0006或0x0000 00009(假定从0x0000 0000 ---0x0000 0005内存存放的是其他数据),那么就不是自然对齐。 2、字节对齐的优缺点 优点: 需要字节对齐的根本原因在于CPU访问数据的效率问. 阅读详情

文章系转载,便于整理和分类,源文地址:https://blog.youkuaiyun.com/suifengpiao_2011/article/details/47260085

linux中定义对齐字节

typedef struct  sdk_handler {
	char comm_ver[10]; 
	char name[20];
	char reserve[20];
}PACKED  sdk_handler_t;

#define PACKED //__attribute__((aligned(1),packed))  // 一字节对齐

首先我们先看看下面的C语言的结构体:

typedef struct MemAlign  
{  
    int a;  
    char b[3];  
    int c;  
}MemAlign;  

以上这个结构体占用内存多少空间呢?也许你会说,这个简单,计算每个类型的大小,将它们相加就行了,以32为平台为例,int类型占4字节,char占用1字节,所以:4 + 3 + 4 = 11,那么这个结构体一共占用11字节空间。好吧,那么我们就用实践来证明是否正确,我们用sizeof运算符来求出这个结构体占用内存空间大小,sizeof(MemAlign),出乎意料的是,结果居然为12?看来我们错了?当然不是,而是这个结构体被优化了,这个优化有个另外一个名字叫“对齐”,那么这个对齐到底做了什么样的优化呢,听我慢慢解释,再解释之前我们先看一个图,图如下:

相信学过汇编的朋友都很熟悉这张图,这张图就是CPU与内存如何进行数据交换的模型,其中,左边蓝色的方框是CPU,右边绿色的方框是内存,内存上面的0~3是内存地址。这里我们这张图是以32位CPU作为代表,我们都知道,32位CPU是以双字(DWORD)为单位进行数据传输的,也正因为这点,造成了另外一个问题,那么这个问题是什么呢?这个问题就是,既然32位CPU以双字进行数据传输,那么,如果我们的数据只有8位或16位数据的时候,是不是CPU就按照我们数据的位数来进行数据传输呢?其答案是否定的,如果这样会使得CPU硬件变的更复杂,所以32位CPU传输数据无论是8位或16位都是以双字进行数据传输。那么也罢,8位或16位一样可以传输,但是,事情并非像我们想象的那么简单,比如,一个int类型4字节的数据如果放在上图内存地址1开始的位置,那么这个数据占用的内存地址为1~4,那么这个数据就被分为了2个部分,一个部分在地址0~3中,另外一部分在地址4~7中,又由于32位CPU以双字进行传输,所以,CPU会分2次进行读取,一次先读取地址0~3中内容,再一次读取地址4~7中数据,最后CPU提取并组合出正确的int类型数据,舍弃掉无关数据。那么反过来,如果我们把这个int类型4字节的数据放在上图从地址0开始的位置会怎样呢?读到这里,也许你明白了,CPU只要进行一次读取就可以得到这个int类型数据了。没错,就是这样,这次CPU只用了一个周期就得到了数据,由此可见,对内存数据的摆放是多么重要啊,摆放正确位置可以减少CPU的使用资源。

那么,内存对齐有哪些原则呢?我总结了一下大致分为三条:

  • 第一条:第一个成员的首地址为0

  • 第二条:每个成员的首地址是自身大小的整数倍

    • 第二条补充:以4字节对齐为例,如果自身大小大于4字节,都以4字节整数倍为基准对齐。若内嵌结构体,则内嵌结构体的首地址也要符合此条,只不过自身大小用内嵌结构体的最大成员来表示。补齐时,内嵌结构体和外部结构体都要满足补齐,内嵌机构体中的补齐以其内部最大成员表示;外部结构体以自身基础成员和内嵌结构体的最大成员之间的较大者表示。
  • 第三条:最后以结构总体对齐。

    • 第三条补充:以4字节对齐为例,取结构体中最大成员类型倍数,如果超过4字节,都以4字节整数倍为基准对齐。(其中这一条还有个名字叫:“补齐”,补齐的目的就是多个结构变量挨着摆放的时候也满足对齐的要求。)

    上述的三原则听起来还是比较抽象,那么接下来我们通过一个例子来加深对内存对齐概念的理解,下面是一个结构体,我们动手算出下面结构体一共占用多少内存?假设我们以32位平台并且以4字节对齐方式:

#pragma pack(4)  
typedef struct MemAlign  
{  
    char a[18];  
    double b;     
    char c;  
    int d;    
    short e;      
}MemAlign; 

下图为对齐后结构如下:

我们就以这个图来讲解是如何对齐的:
第一个成员(char a[18]):首先,假设我们把它放到内存开始地址为0的位置,由于第一个成员占18个字节,所以第一个成员占用内存地址范围为0~18。
第二个成员(double b):由于double类型占8字节,又因为8字节大于4字节,所以就以4字节对齐为基准。由于第一个成员结束地址为18,那么地址18并不是4的整数倍,我们需要再加2个字节,也就是从地址20开始摆放第二个成员。
第三个成员(char c):由于char类型占1字节,任意地址是1字节的整数倍,所以我们就直接将其摆放到紧接第二个成员之后即可。
第四个成员(int d):由于int类型占4字节,但是地址29并不是4的整数倍,所以我们需要再加3个字节,也就是从地址32开始摆放这个成员。
第五个成员(short e):由于short类型占2字节,地址36正好是2的整数倍,这样我们就可以直接摆放,无需填充字节,紧跟其后即可。
这样我们内存对齐就完成了。但是离成功还差那么一步,那是什么呢?对,是对整个结构体补齐,接下来我们就补齐整个结构体。那么,先让我们回顾一下补齐的原则:“以4字节对齐为例,取结构体中最大成员类型倍数,如果超过4字节,都以4字节整数倍为基准对齐。”在这个结构体中最大类型为double类型(占8字节),又由于8字节大于4字 节,所以我们还是以4字节补齐为基准,整个结构体结束地址为38,而地址38并不是4的整数倍,所以我们还需要加额外2个字节来填充结构体,如下图红色的就是补齐出来的空间:

到此为止,我们内存对齐与补齐就完毕了!接下来我们用实验来证明真理,程序如下:

#include <stdio.h>  
#include <memory.h>  
  
// 由于VS2010默认是8字节对齐,我们  
// 通过预编译来通知编译器我们以4字节对齐  
#pragma pack(4)  
  
// 用于测试的结构体  
typedef struct MemAlign  
{  
    char a[18]; // 18 bytes  
    double b;   // 08 bytes   
    char c;     // 01 bytes  
    int d;      // 04 bytes  
    short e;    // 02 bytes  
}MemAlign;  
  
int main()  
{  
    // 定义一个结构体变量  
    MemAlign m;  
    // 定义个以指向结构体指针  
    MemAlign *p = &m;  
    // 依次对各个成员进行填充,这样我们可以  
    // 动态观察内存变化情况  
    memset( &m.a, 0x11, sizeof(m.a) );  
    memset( &m.b, 0x22, sizeof(m.b) );  
    memset( &m.c, 0x33, sizeof(m.c) );  
    memset( &m.d, 0x44, sizeof(m.d) );  
    memset( &m.e, 0x55, sizeof(m.e) );  
    // 由于有补齐原因,所以我们需要对整个  
    // 结构体进行填充,补齐对齐剩下的字节  
    // 以便我们可以观察到变化  
    memset( &m, 0x66, sizeof(m) );  
    // 输出结构体大小  
    printf( "sizeof(MemAlign) = %d", sizeof(m) );  
}  

程序运行过程中,查看内存如下:

其中,各种颜色带下划线的代表各个成员变量,蓝色方框的代表为内存对齐时候填补的多余字节,由于这里看不到补齐效果,我们接下来看下图,下图篮框包围的字节就是与上图的交集以外的部分就是补齐所填充的字节。

在最后,我在谈一谈关于补齐的作用,补齐其实就是为了让这个结构体定义的数组变量时候,数组内部,也同样满足内存对齐的要求,为了更好的理解这点,我做了一个跟本例子相对照的图:

补充:

1)对于结构体中有数组的,将数组作为基本数据类型来处理对齐;

2)对于结构体内嵌套结构体成员的,结构体成员的对齐和补齐原则:已最大成员作为内结构体整体的大小去匹配;

C语言中的结构体对齐是什么?如何控制结构体对齐方式? 结构体对齐是指如何在内存中安排结构体的成员,以便使它们在内存中对齐到合适的边界位置。在许多计算机体系结构中,访问未对齐的内存可能会导致性能下降或引发硬件异常。因此,结构体对齐是一种重要的优化机制,它确保结构体成员被合理地分配到内存中,以最大程度地提高程序的性能。结构体对齐的主要目标是确保结构体的成员在内存中的地址是某个固定值的倍数,通常是成员的大小或特定硬件要求的大小。这个固定值称为对齐边界或对齐因子。结构体对齐的方式可以因编译器和目标硬件而异。 阅读详情

相关推荐

__attribute__ 机制使用

这是属性经常看见,但是也没仔细的看看他具体如何使用,最近浏览博客,发现这个属性其实可以做好多事情的。因此,这里就打算把这个属性详细的学习一下。 介绍 __attribute 其实是个编译器指令,告诉编译器声明的特性,或者让编译器进行更多的错误检查和高级优化。 attribute 可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。 __attribute 是GCC的特性,LLVM借鉴过来,又对其进行了扩

天涯路的专栏 2640

__attribute__ 关键字小结

参考连接: C语言字节对齐 __align(),__attribute((aligned (n))),#pragma pack(n) - windy_net - 博客园转载地址 :http://blog.youkuaiyun.com/21aspnet/article/details/6729724 一、概念 对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整https://www.cnblogs.com/ransn/p/5081198.html1.作用:字节对齐的作用不仅是便于cpu快速访问,同时

yinweiwuzhisuoyixue的博客 639

vue高德地图POI关键字搜索定位

最近在项目中遇到了关于地图的问题,首先为了满足需求从而使用的是JSAPI为2.0版本的。需求是根据关键字搜索定位到该位置。值得注意的是在使用 AMap.Event.addListener时 Event一定要大写的E,不然页面会报错。在地图上定义一个输入框,根据输入的位置进行提示,然后点击后跳转到对应的位置并打点标记。JSAPI主要使用这两个。

YL 2136

使用__attribute__处理结构对齐问题

GNU C扩展的__attribute__ 机制被用来设置函数、变量、类型的属性,其用得较多的是处理字节对齐的问题。 __attribute__ 的语法为:CODE:__attribute__ ((语法列表))参数aligned(number) [number为最小对齐的字节数]是用得较多的一个。另一个是参数packed 表示“使用最小对齐”方式,即对变量是字节对齐,对于域是

abc的专栏 1640

关于mos管的压降问题(项目遇到问题总结)

在研发过程中没有出现问题的板子,到了小批时竟出现雷达一直在触发???找了大几天,没有头绪。心中疑惑颇多,加上老板催促,自考等原因,真是压力山大。4月份自考,只有差不多一个月时间了吧,没有什么大的收获,反而在查找硬件问题的过程中,发现了一个自己忽视的一个问题,就是关于Mos管的压降问题。 备考的过程崎岖不平,工作又问题多多,孰轻孰重,如何取舍?从心理来说,不想取舍什么,只是有所得就可以,过不了就过不了呗,已经毕业十五年了,没这个本科文凭不也过来了吗?只是代表了自己在这一段时间的思考,自己兴趣吧,没什么大不了

guangod的博客 2万+

28377D Bootloader

架构

a6100309120的博客 6013

linux 64位结构体对齐,struct结构体字节对齐

//--------------------------------------------------------本文目录结构|-为什么结构体内存对齐|-结构体内存对齐规则|-具体举例//--------------------------------------------------------一、为什么结构体内存对齐其实我们都知道,结构体只是一些数据的集合,它本身什么都没有。我们所谓的结构...

weixin_42421710的博客 651

内网开发必备:5分钟搞定WSL2离线安装(含Ubuntu迁移避坑指南)

本文详细介绍了在内网环境下快速完成WSL2离线安装的完整流程,包括系统兼容性检查、Linux内核更新包安装以及Ubuntu镜像的离线部署。特别针对外网Ubuntu环境迁移至内网时的用户权限、系统路径等常见问题提供了实用解决方案,帮助开发者高效搭建Linux开发环境。

weixin_29255731的博客 402

Linux下C语言——结构体对齐

结构体对齐的步骤:             1、结构体各成员对齐             2、整个结构体圆整 结构体对齐的特定对齐值:   ...

Mastema 1723

浅谈Android MVI架构---大自然的搬运工~~~

浅谈 Android MVI架构

hong_world的博客 2158

Z-Image Turbo随机性增强插件的下载教程及使用方法 z-image生成图像太相似怎么办 Z-Image Turbo 整合包下载

Z-Image Turbo 是出了名的“seed 不敏感”,非常难做多样化图像创作。ComfyUi-ConditioningNoiseInjection 插件通过在conditioning(提示词编码)阶段加入可控噪声,成功解决了 Turbo 随机性不足的问题。它不仅能让 Turbo 产生更丰富的构图差异,还能保持主题稳定,是目前我测试过最有效的 Turbo 随机性增强工具。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1984

linux c 结构体对齐 宏,结构体对齐声明办法

1 ANSI C规定ANSI C规定一种结构类型的大小是它所有字段的大小以及字段之间或字段尾部的填充区大小之和。填充区就是为了使结构体字段满足内存对齐要求而额外分配给结构体的空间。那么结构体本身有对齐要求,ANSI C标准规定结构体类型的对齐要求不能比它所有字段中要求最严格的那个宽松,可以更严格。2 WIN32和Linux平台下的对齐基本规则许多实际的计算机系统对基本类型数据在内存中存放的位置有...

weixin_33837846的博客 567

菱Q系列串行通信模块QJ71C24N:概述与特点

该模块支持多种串行通信协议,包括RS-232、RS-422和RS-485等,并提供了可靠的数据传输和高效的通信性能。菱Q系列串行通信模块QJ71C24N是一款功能强大的模块,具有多种通信协议支持、高速数据传输、多点通信能力和简化配置与使用等特点。简化配置和使用:QJ71C24N模块具有简单易用的配置工具和用户界面,使得用户能够快速进行模块的设置和调整。高速数据传输:QJ71C24N模块提供了高速的数据传输能力,可实现快速的数据交换和通信。本文将介绍QJ71C24N模块的概述和特点,并提供相应的源代码示例。

IunScala的博客 1931

linux windows 结构体,Linux下C语言——结构体对齐

结构体对齐的步骤:1、结构体各成员对齐2、整个结构体圆整结构体对齐的特定对齐值:1、自身对齐值: 自身对齐值就是结构体变量里每个成员的自身大小;2、指定对齐值: 指定对齐值是由宏#pragma pack (N)指定的值,里面的N必须是2的幂次方,如1,2,4,8,16等。如果没有通过#pragma pack宏那么在32位的Linux主机上默认指定对齐值为4,64位的Linux主机上默认指定对齐值为...

weixin_39558804的博客 384

基于Simulink的光伏电站AGC/AVC协调控制仿真

摘要:本文基于Simulink构建光伏电站AGC/AVC协调控制仿真模型,通过分层控制架构实现有功-无功解耦与储能协同。系统包含100kW光伏阵列、50kWh储能及逆变器组件,采用PID控制器实现AGC频率调节(±0.1Hz)和Q-V下垂控制实现AVC电压稳定(±2%)。仿真验证了三种工况下协调控制的有效性:正常调度时储能充电20kW;负荷突增时储能15kW放电维持频率;光照骤降时储能30kW放电并吸收2kVAR无功稳定电压。结果表明,该方案可使频率/电压偏差分别控制在0.1Hz和7.6V内,响应时间&lt

xiaoheshang_123的博客 236

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

linux内核分析 —— zone结构体对齐

可以看到,这两个宏默认都是按L1的cache line大小对齐,对结构体整体的修饰表示zone结构体类型的变量的起始地址按L1 cacheline对齐,在结构体内部表示紧跟在后面结构体成员变量的地址按L1 cacheline对齐。在很多linux内核资料上都说为了防止伪cache共享,对zone结构体进行了特殊的设计。以我自己的测试环境为例,是x86_64架构的,L1 cacheline的长度定义在。可以看到上面的这些zone的起始地址都是对齐的,而且是512字节对齐。在这个结构体内部利用。

pengdonglin137的专栏 2972

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

linux中结构体对齐【转】

转自:https://blog.youkuaiyun.com/suifengpiao_2011/article/details/47260085 linux中定义对齐字节 typedef struct  sdk_handler { char comm_ver[10];  char name[20]; char reserve[20]; }PACKED  sdk_handler_t;   #...

weixin_34357962的博客 145

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

linux C语言结构体对齐

linux C语言结构体对齐 linux C语言结构体对齐(32位对齐) posted on 2016-08-03 15:23 xuhaohunter 阅读(...) 评论(...) 编辑 收藏 var allowComments=true,cb_blogId=2...

weixin_33813128的博客 163

Linux下关于结构体对齐的总结

Linux下关于结构体对齐的总结 关于对齐模数 许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数。当一种类型S的对齐模数与另一种类型T的对齐模数的比值是大于1的整数,我们就称类型S的对齐要求比T强(严格),而称T比S弱(宽松)。 对于基本数据

penzchan的专栏 1811

linux 编译 结构体对齐,Linux下关于结构体对齐的总结

关于对齐模数许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数。当一种类型S的对齐模数与另一种类型T的对齐模数的比值是大于1的整数,我们就称类型S的对齐要求比T强(严格),而称T比S弱(宽松)。对于基本数据类型(int char),他们占用的内存空间在一个确定硬件系...

weixin_42300927的博客 199

linux 编译 结构体对齐,C语言之结构体以及结构体对齐访问

1:简单理解,结构体就是数组的进一步发展,数据的优点和缺陷在于数据里面是元素类型必须相同,但是结构体没有这个要求,结构体里面元素的类型可以相同也可以不同。2:结构体的定义:struct student{int age;char name[20];}s1;上面这种方法是结构体定义的同时定义变量,结构体的定义有两部分组成struct studen:结构体的类型s1:类型为struct student的...

weixin_32039589的博客 195

linux 编译 结构体对齐,linux 结构体 对齐

这么晚了,我是来帮顶的。。。。真心不会C######回复 @中山野鬼 : Microsoft认为自己就是标准。######多谢多谢。。。。。。。。。真心想不出windows为什么这么变态不按posix的标准走。。。。。######留名,php是最好的语言→_→######va_list是个啥东西啊。######这是win的问题还是cygwin的问题啊?######引用来自“欣儿”的评论这是win...

weixin_33462927的博客 136
上一篇: 条件变量与锁
下一篇: Redis sds packed对齐理解
不与天斗8866
博客等级 码龄18年 651粉丝 196原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值