一,内存地址对齐的概念

   计算机内存中排列、访问数据的一种方式,包含基本数据对齐和结构体数据对齐。

   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下字节对齐的更多相关文章

  1. Windows下struct和union字节对齐设置以及大小的确定(一 简介和结构体大小的确定)

    在windows下设置字节对齐大小的方式,目前我了解有三种: 1. 在编译程序时候的编译选项  /Zp[n],如 cl /Zp4 表示对齐大小是4字节: 2. 预处理命令   #pragma pack ...

  2. (原创)Linux下一定要4字节地址对齐操作

    Linux下一定要4字节地址对齐操作:“血”的教训,一定不要忘记!!! 当然不仅仅是Linux下,所有的32位机都应该如此!!!

  3. x86_64 Linux 运行时栈的字节对齐

    前言 C语言的过程调用机制(即函数之间的调用)的一个关键特性(起始大多数编程语言也是如此)都是使用了栈数据结构提供的后进先出的内存管理原则.每一个函数的栈空间被称为栈帧,一个栈帧上包含了保存的寄存器. ...

  4. 【Linux】C字节对齐

    原文地址:https://www.jianshu.com/p/e8fcc01041a7 什么是对齐,以及为什么要对齐: 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问 ...

  5. 不同编译器下,定义一个地址按x字节对齐的数组

    以前一直用MDK,用__align(4)就可以定义一个首地址被4整除.地址按4字节对齐的数组,但今天用IAR发现这么写编译报错. 搜了一下才发现,原来不同的编译器,需要用不同的表达方式: #if de ...

  6. keil mdk+stm32的ac5和 ac6两个编译器下的字节对齐操作方法

    最近在使用ac6.9的编译器,编译速度是真的很快,使用stm32的hal库编译速度也比ac5的编译器快很多.本文试验stm32中字节对齐的代码测试,主要是结构体,因为结构体中实际项目中用到最多,同时在 ...

  7. C语言:内存字节对齐详解[转载]

    一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...

  8. C++成员变量内存对齐问题,ndk下非对齐的内存访问导致BUS_ADRALN

    同样的代码,在vs下运行正常,在android ndk下却崩溃: signal 7(SIGBUS),code 1 (BUS_ADRALN),fault addr 0xe6b82793 Func(sho ...

  9. [转]Linux下的lds链接脚本详解

    转载自:http://linux.chinaunix.net/techdoc/beginner/2009/08/12/1129972.shtml     一. 概论 每一个链接过程都由链接脚本(lin ...

随机推荐

  1. ●UVA 10674 Tangents

    题链: https://vjudge.net/problem/UVA-10674 题解: 计算几何,求两个圆的公切线. <算法竞赛入门经典——训练指南>P266,讲得很清楚的. 大致是分为 ...

  2. UVA 11584 划分回文字串

    将其划分为尽可能少的回文串 dp[i] = min(dp[i],dp[j] + 1)    来表示j+1~i是回文串 #include <iostream> #include <cs ...

  3. 【AHOI2005】病毒检测

    题目描述 科学家们在Samuel星球上的探险仍在继续.非常幸运的,在Samuel星球的南极附近,探险机器人发现了一个巨大的冰湖!机器人在这个冰湖中搜集到了许多RNA片段运回了实验基地. 科学家们经过几 ...

  4. Codeforces Round#403 (Div. 1)

    唉,昨天晚上迷迷糊糊地去打cf,结果fst两题,掉回蓝了... A.Andryusha and Colored Balloons 题意:给定一棵树,任意两个距离小等于二的点不能染相同的颜色,求最小颜色 ...

  5. 4455[Zjoi2016]小星星 容斥+dp

    4455: [Zjoi2016]小星星 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 527  Solved: 317[Submit][Status] ...

  6. SpringBoot学习之集成dubbo

    一.摘自官网的一段描述 1.背景 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用架构 ...

  7. 解决ansible首次连接host服务器需验证问题

    问题描述: [root@iZm5e79rtwsq2hm57teyk5Z ansible]# ansible aofeng -f 5 -m ping 47.93.18.191 | FAILED! =&g ...

  8. 【python进阶】Garbage collection垃圾回收1

    前言 GC垃圾回收在python中是很重要的一部分,同样我将分两次去讲解Garbage collection垃圾回收,此篇为Garbage collection垃圾回收第一篇,下面开始今天的说明~~~ ...

  9. c++自定义类型

    /* --自定义数据类型 结构体 共用体 共用体的数据成员在存储数据时共享存储空间,修改一个成员也会改变另一个成员的值 枚举型 如果要使变量只能使用有限的几个值,则应当使用枚举体.之所以叫枚举体,就是 ...

  10. Programming In Scala笔记-第六章、函数式对象

    这一章主要是以定义和完善一个有理数类Rational为线索,分析和介绍有关类定义,构造函数,方法重写,变量定义和私有化,以及对操作符的定义等. 一.Rational类定义和构造函数 1.定义一个空类 ...