Hello C(八)——内存字节对齐
一、内存字节对齐简介
1、内存字节对齐
计算机中内存空间都是按照字节划分的,从理论上讲对任何类型的变量的访问可以从任何地址开始,但是在程序实际编译过程中,编译器会对数据类型在编译过程中进行优化对齐,编译器会将各种类型数据按照一定的规则在空间上排列,而不是顺序的排放,这就是内存字节对齐。
2、内存字节对齐原因
不同硬件平台对存储空间的处理是不同的。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如某些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐。其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据,这样数据读取效率就会很差。
二、内存字节对齐的规则
1、数据类型自然边界对齐
各种数据类型的自然边界对齐值如下:
数据类型 |
对齐值 |
char |
1 |
short |
2 |
int |
4 |
long |
4(8,64位) |
float |
4 |
double |
8 |
void * |
4(8,64位) |
2、结构体、类的自身对齐
为结构体分配内存时,分配的内存大小至少是各个字段的长度和。通常,分配的结构体的长度会大于结构体各个字段的长度和,因为结构体需要对齐,即结构体各字段之间需要填充。
缺省情况下,编译器为结构体的每个成员按其自然边界对齐方式分配空间,按照每个成员被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构体的地址相同。结构体整体的默认字节对齐值是结构体中的所有成员中对齐参数最大的一个的值,结构体长度的计算必须取所用过的所有对齐参数的整数倍。
结构体中成员的对齐方式取决于指定对齐方式对齐值和成员自身自然边界对齐值两者中较小的值。
结构体整体对齐方式取决于结构体中所有成员的自然边界对齐值的最大值和指定对齐值两者中最小的值。
3、编译器指定对齐
内存字节对齐是GCC编译器对C语言进行的扩展。在缺省情况下,C编译器为每一个变量或是数据单元按其自然边界对齐条件分配空间。同时GCC编译器规定了两种内存字节对齐的方法:
A、伪指令方式
#pragma pack(n) //n的取值可以为1、2、4、8,在编译过程中按照n个字节对齐
#pragma pack() //取消指定对齐,按照编译器的优化对齐方式对齐
GCC编译器不建议使用#pragma进行内存字节对齐,而且#pragma最多只能支持8字节的对齐。如果n大于8则编译器会报警告,编译器将会按8字节对齐。
warning: alignment must be a small power of two, not 9 [-Wpragmas]
B、属性设置方式
__attribute__ ((packed)); //取消结构在编译过程中的优化对齐。
__attribute__ ((aligned (n))); //让所作用的结构体、类的成员对齐在n字节自然边界上,如果结构中有成员的长度大于n,则按照机器字长来对齐。n=1,2,4,8,16…
GCC推荐使用方式
C、两种对齐方式的区别
#pragma pack(n) 对齐方式告诉编译器结构体或类内部的成员变量相对于第一个变量的地址的偏移量的对齐方式,缺省情况下,编译器按照自然边界对齐,当变量所需的自然对齐边界比n大时,按照n对齐,当变量所需的自然对齐边界比n小时,按照自然边界对齐。n最大只能为8。
__attribute__((aligned(m)))对齐方式告诉编译器一个结构体或者类或者联合或者一个类型的变量(对象)分配地址空间时的地址对齐方式。如果__attribute__((aligned(m)))作用于一个类型,那么该类型的变量在分配地址空间时,其存放的地址一定按照m字节对齐(m必须是2的幂次方);如果类型中的成员的自然边界对齐值大于m,则按照机器字长对齐。类型占用的空间,即大小,是m的整数倍,以保证在申请连续存储空间的时候,每一个元素的地址也是按照m字节对齐。
实例对比如下:
struct test{char a;int b;short c;char *p;double d;
}__attribute__((aligned(4)));//实际有效指定对齐值为8字节(机器字长)sizeof(struct test);//32字节#pragma pack(4)
struct test{char a;int b;short c;char *p;double d;
};//指定对齐值小于结构体中成员的自然边界对齐值8字节,有效对齐值为4字节#pragma pack()
sizeof(struct test);//28字节
三、内存字节对齐实例
环境:Ubuntu x64,GCC 4.6.3
代码示例:
1字节对齐:
#pragma pack(1)
struct test{char a;int b;short c;
};
#pragma pack()sizeof(struct test);//7字节
结构体成员中数据类型对齐的最大值为4字节,指定对齐值为1字节,结构体整体对齐值为1字节
2字节对齐:
#pragma pack(2)
struct test{char a;int b;short c;
};
#pragma pack()sizeof(struct test);//8字节
结构体成员中数据类型对齐的最大值为4字节,指定对齐值为2字节,结构体整体对齐值为2字节
4字节对齐:
#pragma pack(4)struct test{char a;int b;short c;
};
#pragma pack()sizeof(struct test);//12字节
结构体成员中数据类型对齐的最大值为4字节,指定对齐值为4字节,结构体整体对齐值为4字节
8字节对齐:
#pragma pack(8)
struct test{char a;int b;short c;
};
#pragma pack()sizeof(struct test);//12字节
结构体成员中数据类型对齐的最大值为4字节,指定对齐值为8字节,结构体整体对齐值为4字节
#pragma pack(12)
struct test{char a;int b;short c;double d;
};sizeof(struct test);//24字节
结构体成员中数据类型对齐的最大值为8字节,指定对齐值为8字节,结构体整体对齐值为8字节
struct test{char a;int b;short c;double d;
}__attribute__((aligned(2)));sizeof(struct test);//24字节
结构体成员中数据类型对齐的最大值为8字节,有效指定对齐值为8字节(指定对齐值为2字节,小于结构体中成员的最大自然边界对齐值8字节,对齐值为机器字长8字节),结构体整体对齐值为8字节
struct test{char a;int b;short c;char *p;double d;
}__attribute__((aligned(2)));sizeof(struct test);//40字节
结构体成员中数据类型对齐的最大值为8字节,有效指定对齐值为8字节(指定对齐值为2字节,小于结构体中成员的最大自然边界对齐值8字节,对齐值为机器字长8字节),结构体整体对齐值为8字节
struct test{char a;int b;short c;char vector[10];char *p;double d;
}__attribute__((aligned(16)));sizeof(struct test);//48字节
四、内存字节对齐的应用场合
在设计不同CPU下的通信协议时,或者编写硬件驱动程序时寄存器的结构都需要按一字节对齐。
五、ARM平台的内存字节对齐
在ARM中,有ARM和Thumb两种指令。
ARM指令:每执行一条指令,PC的值加4个字节(32bits)。一次访问4字节内容,该字节的起始地址必须是4字节对齐的位置上,即地址的低两位为bits[0b00],也就是说地址必须是4的倍数。
Thumb指令:每执行一条指令,PC的值加2个字节(16bits)。一次访问2字节内容,该字节的起始地址必须是2字节对齐的位置上,即地址的低两位为bits[0b0],也就是说地址必须是2的倍数。
ARM汇编程序设计中的字节对齐
.align n
.align的作用在于对指令或者数据的存放地址进行对齐,有些CPU架构要求固定的指令长度并且存放地址相对于2的幂指数圆整,否则程序无法正常运行
ARM汇编器并不直接使用.align提供的参数作为对齐目标,而是使用2^n的值,比如这里的参数为4,那么圆整对象为2^4 = 16。缺省为4。
Hello C(八)——内存字节对齐相关推荐
- 更改结构体的内存字节对齐方式--经典
结构体字节对齐 http://blog.163.com/ecy_fu/blog/static/4445126200910603739941/ http://hi.baidu.com/skyland_l ...
- C语言内存字节对齐小结
在C语言面试和考试中经常会遇到内存字节对齐的问题.今天就来对字节对齐的知识进行小结一下. 首先说说为什么要对齐.为了提高效率,计算机从内存中取数据是按照一个固定长度的.以32位机为例,它每次取32个位 ...
- 详解结构体、类等内存字节对齐
先说个题外话:早些年我学C程序设计时,写过一段解释硬盘MBR分区表的代码,对着磁盘编辑器怎么看,怎么对,可一执行,结果就错了.当时调试也不太会,又根本没听过结构体对齐这一说,所以,问题解决不了,好几天 ...
- 快速弄懂内存字节对齐
字节对齐有三原则: 1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员 ...
- 【C】C语言内存字节对齐
原博地址:https://blog.csdn.net/andy572633/article/details/7213465 首先说说为什么要对齐.为了提高效率,计算机从内存中取数据是按照一个固定长度的 ...
- 结构体字节对齐(转)
结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是 ...
- mysql字节对齐_结构体字节对齐(转)
结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是 ...
- c语言union字节相同大小不同,C语言的struct/union字节对齐
C语言的一大优势就是对内存空间的控制,当然,一般情况下对于开发人员来说都是透明的.看一个始终困扰初学者的问题:字节对齐! 先看四个重要的基本概念: 1.数据类型自身的对齐值: 对于char型数据,其自 ...
- C语言基础 - 结构体类型字节对齐总结
一.什么是字节对齐 在计算机中,内存空间是按照字节(1B = 8 bit)划分的,每一个字节都有一个编号,这就是字节的地址.理论上可以从任意起始地址访问任意数据类型的变量,但在实际使用中,访问特定数据 ...
最新文章
- MySQL抓包工具:MySQL Sniffer
- 【android-tips】如何在android应用中插入百度广告(附源码)
- 【springboot】SpringBootTest 测试时, application.properties 文件的查找顺序
- magento xml配置详解(2)
- 运营商iptv服务器,IPTV 服务器
- DDoS原理、分类与防御
- SMTP的几个端口的比较
- 收益率-计算方法介绍
- 作用域public,protected,private, 以及不写时的区别
- 各种提权、渗透经验技巧总结大全(下)
- 基于STM32的ESP8266天气时钟(1)---------AT指令获取天气数据
- E2224和E5-2630v4的区别?
- un7.2:IDEA中实现登录功能
- CSDN有哪些值得学习的专栏?
- axios拦截器、ElementUI组件的使用
- Linux内核之PCI设备
- 糖果车站的街外小雪初晴
- 邮箱POP3/SMTP设置(发送邮箱问题汇总)
- OSChina 周四乱弹 ——心有鱼,而力不足
- 编程范式(斯坦福大学)学习笔记《二》