linux下字节对齐
一,内存地址对齐的概念
计算机内存中排列、访问数据的一种方式,包含基本数据对齐和结构体数据对齐。
32位系统中,数据总线宽度为32,每次能够读取4字节数据。地址总线为32,最大寻址空间为4GB。但是由于最低位A[0]~A[1]是不用于寻址的,因此只能访问4的倍数的地址空间,但是寻址空间还是2^30*字长=4GB。
因此内存中除了结构体中成员变量之外的基本类型的开始的手地址最低两位都是0。基本类型数据对齐就是数据在内存中的偏移地址必须是一个字的倍数,以提高读取数据时的性能。为了对齐数据,必须在上个数据结束和下个数据开始处插入一些字节,这就是结构体数据对齐。
二,不进行对齐的影响
例如int a的地址是0x00fffff3,则其字节分布在0x00fffff3~0x00fffff6空间内,为了读取这个int,cpu必须对 0x00fffff0和0x00fffff4进行两次内存读取,并处理得出的中间结果。两次内存访问将会浪费大量的时间,因为内存访问的速度远小于CPU 处理指令的速度。
三,结构体的内存地址对齐
结构体本身必须是4字节对齐的,而其成员变量则处理规则如下。
以下是Microsoft和GNU对x86架构32位系统的结构体成员的默认对齐方式:
char 1字节对齐
short 2字节对齐
int 4字节对齐
float 4字节对齐
double windows是8字节对齐,linux是4字节对齐
当某一个成员后边的成员变量要求的地址对齐较大,则应该填入一些字节。且总的结构体大小为最大对齐的倍数,因此最后可能还要填充一些字符。
因为上述结构体对齐的原因,将结构体成员按照大小递增/递减方式排序,可以减少结构体占用的空间大小。而这样同时使得对整个结构体的存取的效率变高了(占用小,整个的访问次数可以降低)。
另外一个提高效率的方法是把一些占用字节数较少的成员合并到字节数占用大的成员,形成union类型。
四。准则
其实字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则:
1. 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2. 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;
3. 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。
五.基本概念
字节对齐:计算机存储系统中以Byte为单位存储数据,不同数据类型所占的空间不同,如:整型(int)数据占4个字节,字符型(char)数据占一个字节,短整型(short)数据占两个字节,等等。计算机为了快速的读写数据,默认情况下将数据存放在某个地址的起始位置,如:整型数据(int)默认存储在地址能被4整除的起始位置,字符型数据(char)可以存放在任何地址位置(被1整除),短整型(short)数据存储在地址能被2整除的起始位置。这就是默认字节对齐方式。
六、结构体长度求法
1.成员都相同时(或含数组且数组数据类型同结构体其他成员数据类型):
结构体长度=成员数据类型长度×成员个数(各成员长度之和);
结构体中数组长度=数组数据类型长度×数组元素个数;
2.成员不同且不含其它结构体时;
(1).分析各个成员长度;
(2).找出最大长度的成员长度M(结构体的长度一定是该成员的整数倍);
(3).并按最大成员长度出现的位置将结构体分为若干部分;
(4).各个部分长度一次相加,求出大于该和的最小M的整数倍即为该部分长度
(5).将各个部分长度相加之和即为结构体长度
3.含有其他结构体时:
(1).分析各个成员长度;
(2).对是结构体的成员,其长度按b来分析,且不会随着位置的变化而变化;
(3).分析各个成员的长度(成员为结构体的分析其成员长度),求出最大值;
(4).若长度最大成员在为结构体的成员中,则按结构体成员为分界点分界;
其他成员中有最大长度的成员,则该成员为分界点;
求出各段长度,求出大于该和的最小M的整数倍即为该部分长度
(5).将各个部分长度相加之和即为结构体长度
七、空结构体 struct S5 { }; sizeof( S5 ); // 结果为1
“空结构体”(不含数据成员)的大小不为0,而是1。试想一个“不占空间”的变量如何被取地址、两个不同的“空结构体”变量又如何得以区分呢于是,“空结构体”变量也得被存储,这样编译器也就只能为其分配一个字节的空间用于占位了。
八、有static的结构体 struct S4{ char a; long b; static long c; //静态 };
静态变量存放在全局数据区内,而sizeof计算栈中分配的空间的大小,故不计算在内,S4的大小为4+4=8。
#pragma pack(n)指令设置1.2.4对齐。linux下最高位4.#pragma pack()指令默认为四。
九.union
union的长度取决于其中的长度最大的那个成员变量的长度。即union中成员变量是重叠摆放的,其开始地址相同。
其实union(共用体)的各个成员是以同一个地址开始存放的,每一个时刻只可以存储一个成员,这样就要求它在分配内存单元时候要满足两点:
1.一般而言,共用体类型实际占用存储空间为其最长的成员所占的存储空间;
2.若是该最长的存储空间对其他成员的元类型(如果是数组,取其类型的数据长度,例int a[5]为4)不满足整除关系,该最大空间自动延伸;
我们来看看这段代码:
union mm{ char a;//元长度1 int b[5];//元长度4 double c;//元长度8 int d[3]; };
本来mm的空间应该是sizeof(int)*5=20;但是如果只是20个单元的话,那可以存几个double型(8位)呢?两个半?当然不可以,所以mm的空间延伸为既要大于20,又要满足其他成员所需空间的整数倍,即24
所以union的存储空间先看它的成员中哪个占的空间最大,拿他与其他成员的元长度比较,如果可以整除就行。
linux下字节对齐的更多相关文章
- Windows下struct和union字节对齐设置以及大小的确定(一 简介和结构体大小的确定)
在windows下设置字节对齐大小的方式,目前我了解有三种: 1. 在编译程序时候的编译选项 /Zp[n],如 cl /Zp4 表示对齐大小是4字节: 2. 预处理命令 #pragma pack ...
- (原创)Linux下一定要4字节地址对齐操作
Linux下一定要4字节地址对齐操作:“血”的教训,一定不要忘记!!! 当然不仅仅是Linux下,所有的32位机都应该如此!!!
- x86_64 Linux 运行时栈的字节对齐
前言 C语言的过程调用机制(即函数之间的调用)的一个关键特性(起始大多数编程语言也是如此)都是使用了栈数据结构提供的后进先出的内存管理原则.每一个函数的栈空间被称为栈帧,一个栈帧上包含了保存的寄存器. ...
- 【Linux】C字节对齐
原文地址:https://www.jianshu.com/p/e8fcc01041a7 什么是对齐,以及为什么要对齐: 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问 ...
- 不同编译器下,定义一个地址按x字节对齐的数组
以前一直用MDK,用__align(4)就可以定义一个首地址被4整除.地址按4字节对齐的数组,但今天用IAR发现这么写编译报错. 搜了一下才发现,原来不同的编译器,需要用不同的表达方式: #if de ...
- keil mdk+stm32的ac5和 ac6两个编译器下的字节对齐操作方法
最近在使用ac6.9的编译器,编译速度是真的很快,使用stm32的hal库编译速度也比ac5的编译器快很多.本文试验stm32中字节对齐的代码测试,主要是结构体,因为结构体中实际项目中用到最多,同时在 ...
- C语言:内存字节对齐详解[转载]
一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...
- C++成员变量内存对齐问题,ndk下非对齐的内存访问导致BUS_ADRALN
同样的代码,在vs下运行正常,在android ndk下却崩溃: signal 7(SIGBUS),code 1 (BUS_ADRALN),fault addr 0xe6b82793 Func(sho ...
- [转]Linux下的lds链接脚本详解
转载自:http://linux.chinaunix.net/techdoc/beginner/2009/08/12/1129972.shtml 一. 概论 每一个链接过程都由链接脚本(lin ...
随机推荐
- 【线段树】【BZOJ1798】【AHOI2009】维护序列
还是那个学弟@lher出的丧题之一. 链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1798 题意简析:就是题目啊... 解题思路:显然是线段树 ...
- Python【第三课】 函数基础
本篇内容 函数基本语法及特性 嵌套函数 递归函数 匿名函数 高阶函数 内置函数 1.函数的基本语法及特性 1.1 函数概念 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提 ...
- PTA 旅游规划(25 分)
7-10 旅游规划(25 分) 有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径.如果有若干条 ...
- 浅谈JAVA8引入的接口默认方法
参考 http://blog.csdn.net/wanghao_0206/article/details/52712736 public interface InterfaceTest { publi ...
- SQL AND和OR求值顺序
假如需要列出价格为10美元及以上,且由DLL01或BRS01制造的所有产品.下面的SELECT语句使用组合的AND和OR操作符建立了一个WHERE子句: ; 分析▼ 请看上面的结果.返回的行中有4行价 ...
- Tomcat关闭日志输出
tomcat中禁用catalina.out的输出,又可能很大. 1.直接修改catalina.sh文件的输出语句. 在文件中找到以下内容. if [ -z "$CATALINA_OUT&qu ...
- WPF 窗口居中 & 变更触发机制
窗口居中 & 变更触发机制 解决: 1.单实例窗口,窗口每次隐藏后再显示时,位置居中显示 2.多屏幕下单实例窗口,当父窗口移动到其它屏幕时,单实例窗口再次弹出时,位置才更新到父窗口屏幕. 3. ...
- JS实现2048代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- sublime安装配置
http://www.sublimetext.com.cn/ 打华东师范大学校赛的时候,学长谈论到这个编辑器.自定义背景多行多光标同时编辑酷炫爆了.感觉这是一个万能的文本编辑器.通过配置可以写多种语言 ...
- JavaScript基础知识必知!!!
JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型. JS作用:表单验证,减轻服务端的压力:添加页面动画效果:动态更改页面内容:Ajax网络请求. 下面简单介 ...