gcc 支持 aligned 和 packed 属性指定数据对齐,那么在了解对齐规则之前,需要解决第一个以为,我们为什么需要数据对齐?请看下图:

  相信学过汇编的朋友都很熟悉这张图,这张图就是CPU与内存如何进行数据交换的模型,其中,左边蓝色的方框是CPU,右边绿色的方框是内存,内存上面的0~3是内存地址。这里我们这张图是以32位CPU作为代表,我们都知道,32位CPU是以双字(DWORD)为单位进行数据传输的,也正因为这点,造成了另外一个问题,那么这个问题是什么呢?这个问题就是,既然32位CPU以双字进行数据传输,那么,如果我们的数据只有8位或16位数据的时候,是不是CPU就按照我们数据的位数来进行数据传输呢?其答案是否定的,如果这样会使得CPU硬件变的更复杂,所以32位CPU传输数据无论是8位或16位都是以双字进行数据传输。

好了,有了上面的基础,就可以解释为什么需要内存对齐了。

1. 如果访问大小为一个字节的数据(eg : char 类型),假设该数据放在内存地址1开始的位置,那么这个数据占用的内存地址为1,那么cpu通过一个指令周期,读出地址D0-D7 中的数据到寄存器中,然后通过移位指令移动相应的字节即可访问该数据。

2. 比如,一个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的使用资源。

由于上面解释的原因,gcc为代表的各种编译器默认采用了自然边界对齐的方式,那么什么是自然对齐,什么是对齐的内存地址呢, 请看下面的解释:

a. 一般计算机的内存是以字节(byte,等于8bit)为最小单元的。内存地址相当于从0开始的字节偏移数。如果一个内存地址是N的倍数,我们就说它是N字节对齐的(N-byte aligned)。

b. 对于C/C++中的基本数据类型,假设它的长度为n字节,那么该类型的变量会被编译器默认分配到n字节对齐的内存上。例如,char的长度是1字节,char类型变量的地址将是1字节对齐的(任意值均可); int的长度是4字节,所以int类型变量将被分配到4字节对齐的地址上。这种默认情况下的变量对齐方式又称作自然对齐(naturally aligned)。

  需要说明的是,以上对齐都是gcc编译器帮我们自动完成的,一般情况下,程序员不需要过多的关注上面的内容。但是,如果你是在做一些内存映射相关或者协议相关的工作的时候,你必须很清楚了解数据在内存中每一个字节的组织方式的时候,你就很有必要了解gcc编译器的默认对齐规则了,我们先从aligned和packed两个gcc属性说起.

本篇转载和参考资料:

http://blog.csdn.net/suifengpiao_2011/article/details/47260085

http://blog.shengbin.me/posts/gcc-attribute-aligned-and-packed

gcc数据结构对齐之:why.的更多相关文章

  1. gcc 数据对齐之:总结篇.

    通过上面的分析,总结结构体对齐规则如下: 1.数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragm ...

  2. gcc数据对齐之: howto 2.

    原文链接:http://www.catb.org/esr/structure-packing/ 谁应阅读本文 本文探讨如何通过手工重新打包C结构体声明,来减小内存空间占用.你需要掌握基本的C语言知识, ...

  3. gcc数据对齐之: howto 1.

    GCC支持用__attribute__为变量.类型.函数.标签指定特殊属性.这些不是编程语言标准里的内容,而属于编译器对语言的扩展. 本文介绍其中的两个属性:aligned和packed. align ...

  4. 使用JNA替代JNI调用本地方法

    JNA全称是Java Native Access,是Sun推出的一种调用本地方法技术,比起它的同门师兄JNI,JNA大大简化了调用本地方法的过程,使用也比较方便, JNA是在JNI的基础上完善的,用青 ...

  5. Android反编译(三)之重签名

    Android反编译(三) 之重签名 [目录] 1.原理 2.工具与准备工作 3.操作步骤 4.装X技巧 5.问题 1.原理 1).APK签名的要点 a.所有的应用程序都必须有数字证书 ,Androi ...

  6. (转)Tips for Optimizing C/C++ Code

    本来要自己翻译的,随手搜索了一下,发现五天前已经有人翻译了,我就不重复发明轮子了. 转自:http://blog.csdn.net/yutianzuijin/article/details/26289 ...

  7. 《Tips for Optimizing C/C++ Code》译文

    前不久在微博上看到一篇非常好的短文讲怎样对C/C++进行性能优化,尽管其面向的领域是图形学中的光线跟踪,可是还是具有普遍的意义,将其翻译成中文,希望对大家写高质量代码有帮助. 1.     牢记阿姆达 ...

  8. union 和struct大小计算

    一.字节对齐 现代计算机的内存空间是按照字节(byte)来划分的,字节对齐的意思是在给特定变量类型分配内存空间的时候,变量的内存地址是它本身变量类型大小的整数倍.比如,给int类型的变量a分配地址空间 ...

  9. Android NDK笔记

    目录 Android NDK笔记 AOSP Android repository Android SDK / SDK Tools NDK cmake && ninja lldb adb ...

随机推荐

  1. HGOI 20190816 省常中互测8

    Problem A  有两条以(0,0)为端点,分别经过(a,b),(c,d)的射线,你要求出夹在两条射线中间,且距离(0,0)最近的点(x,y) 对于$100\%$的数据满足$1 \leq T \l ...

  2. jQuery_替换操作

    代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title ...

  3. R_Studio模拟学生成绩对数据简单分析

    模拟产生学生名单,记录高数,英语,网站开发三科成绩,然后进行统计分析 假设有100名学生,起始学号为161304000,各科成绩取整 高数成绩为均匀分布随机函数,都在75分以上 英语成绩为正态分布,平 ...

  4. git介绍以及一些常用命令,加上vim编辑器的简单使用

    https://www.jianshu.com/p/04a6517869b4 vim:进入vim编辑器,如果后接文件名,则进入该文件的编辑模式,看图:①.vim编辑器中,按i进入编辑模式:②.按Esc ...

  5. 分布式-网络通信-线程(socket)

    package OIO; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; i ...

  6. is == 编码与解码

    is 和 ==  主要是数字和字符串的比较 1 区别: ==比较的是两边的值     is比较的是两边值的id    id获取的方法 id() 2 小数据池: -5~256 3 字符串中特殊字符有id ...

  7. windows 安装使用 Memcached

    Windows无官方版本:下载地址http://static.runoob.com/download/memcached-win64-1.4.4-14.zip 安装: 1.解压下载的压缩包2.命令行模 ...

  8. C++入门经典-例3.9-使用嵌套表达式判断一个数是否是3和5的整数倍

    1:代码如下: // 3.9.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using ...

  9. spark streaming 1: SparkContex

    StreamingContext 和SparkContex的用途是差不多的,作为spark stream的入口,提供配置.生成DStream等功能. 总体来看,spark stream包括如下模块: ...

  10. pom文件中的dependencyManagement和dependencies的区别

    dependencies 子项目中,自动继承父项目中的相关依赖 dependencyManagement 只是声明依赖,并不实现引入,因此子项目中需要显示的声明需要用的依赖.如果不在子项目中声明依赖, ...