博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
结构体对齐学习稿
阅读量:4179 次
发布时间:2019-05-26

本文共 1069 字,大约阅读时间需要 3 分钟。

先来说说为什么要有边界对齐:

 

简单说,任何CPU都有一个固定的基本长度,下面以32CPU为例(也有64位或其他的)。CPU在工作时只能按照该长度的整倍数为边界进行内存操作。即只能从地址0326496...处进行存取,而不能从275883等非边界地址处进行。如果一定要取这些非边界地址处的内容,则必须用若干个操作将其凑出来,因而大大影响存取效率。

 

另一方面,一个结构体的设计长度却并不一定是32的倍数,例如一个包含六个字符的结构其设计长度仅为48位。如果多个这样的结构在内存中顺着摆放,则许多结构的起始地址将不在边界处。因此,编译程序总是会将每个结构的尾部都加入一些必要的空白,将其凑成32的整数倍。这就是边界对齐的基本道理。

 

在没有#pragmapack宏的情况下,存在三条原则:

 

原则1、普通数据成员对齐规则:第一个数据成员放在offset0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始

比如int32位机为4字节,则要从4的整数倍地址开始存储

 

原则2、结构体成员对齐规则:如果一个结构里有某些结构体成员,则该结构体成员要从其内部最大元素大小的整数倍地址开始存储。

struct a里存有struct bb里有charintdouble等元素,那b应该从8的整数倍开始存储

 

原则3、结构体大小对齐规则:结构体大小也就是sizeof的结果,必须是其内部成员中最大的对齐参数的整数倍,不足的要补齐

 

还有一条原则:成员对齐有一个重要的条件,即每个成员按自己的方式对齐。其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里默认是8字节)中较小的一个对齐。并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节

 

如果有#pragmapack宏,对齐方式按照宏的定义来。比如上面的结构体前加#pragma pack(1),内存的布局就会完全改变。有了#pragma pack(1),内存不会再遵循原则1和原则3了,按1字节对齐。

 

#pragma pack规定的对齐长度,实际使用的规则是:

结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

也就是说,当#pragmapack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。

而结构整体的对齐,则按照结构体中最大的数据成员和 #pragma pack指定值之间,较小的那个进行。

 

转载地址:http://yiqai.baihongyu.com/

你可能感兴趣的文章
《tiny6410裸机程序》第九章:tiny6410按键控制蜂鸣器程序
查看>>
有关free()函数的一个问题
查看>>
《Android系统学习》之bug定位
查看>>
《Linux内核编程》第七章:USB CORE与USB键鼠驱动
查看>>
《Android系统学习》之JAVA与C混合编程——JNI
查看>>
《C预处理》之#ifndef
查看>>
Android边录边播应用
查看>>
《Linux内核编程》第十三章:Linux对进程内存的二级页式管理
查看>>
ARM协处理器
查看>>
《miniOS分析》前言
查看>>
《Linux内核编程》第十四章:Linux驱动基础
查看>>
Linux平台下ARM-Linux交叉编译工具链
查看>>
Window平台下ADS自带ARMCC编译工具链
查看>>
micro2440/tiny6410使用JLINK直接烧录nand flash
查看>>
C编译器、连接器与可执行机器码文件
查看>>
android linker 浅析
查看>>
802.11 traffic id
查看>>
Android系统wifi分析-手动连接过程
查看>>
设置IP别名Shell脚本
查看>>
Source Insight 宏-单行注释
查看>>