数据的对齐存放

目录

数据对齐概念

对齐

边界对齐

边界不对齐

最简单的对齐策略

对齐举例

对齐方式的设定


数据对齐概念

Alignment:要求数据的地址是相应的边界地址

  • 目前机器字长为32位或64位,主存按一个传送单位(32/64/128位)进行存取,而按字节编址,例如:若传送单位为64位,则每次最多读写64位,即:第0~7字节同时读写,第8~15字节同时读写,……,以此类推。按边界对齐,可使读写数据位于8i~8i+7(i=0,1,2,…) 单元
  • 指令系统支持对字节、半字、字及双字的运算
  • 各种不同长度的数据存放时,有两种处理方式:
    – 按边界对齐(若一个字为32位)
    • 字地址:4的倍数(低两位为0)
    • 半字地址:2的倍数(低位为0)
    • 字节地址:任意
    – 不按边界对齐
    坏处:可能会增加访存次数!

对齐

假设1个字=32位,主存每次最多存取一个字,按字节编址,则每次只能读写某个字地址开始的4个单元中连续的1、2、3或4个字节 。

边界对齐

例如:int i, short k, double x, char c,变量按如下顺序在内存中存储,则:&i=0; &k=4; &x=8; &c=16;。
 

取x:需要2个周期

取j:需要1个周期

边界不对齐

&i=0; &k=4; &x=6; &c=14;

取x:3个周期

取j:2个周期

最简单的对齐策略

按其数据长度进行对齐。

  • – Windows采用策略:int型地址是4的倍数,short型地址是2的倍数,double和long long型的是8的倍数,float型的是4的倍数,char不对齐
  • Linux采用更宽松策略:short型是2的倍数,其他类型如int、float、double和指针等都是4的倍数

对齐举例

struct S1 {
int i;
char c;
int j;
};

struct S2 {
int i;
int j;
char c;
};

在要求对齐的情况下,哪种结构声明更好?

S2比S1好

对齐方式的设定

#pragma pack(n)
• 为编译器指定结构体或类内部的成员变量的对齐方式。
• 当自然边界(如int型按4字节、short型按2字节、float按4字节)比n大时,按n字节对齐。
• 缺省或#pragma pack() ,按自然边界对齐。比n小则按自然边界对齐。


__attribute__((aligned(m)))
• 为编译器指定一个结构体或类或联合体或一个单独的变量(对象)的对齐方式。
• 按m字节对齐(m必须是2的幂次方),且其占用空间大小也是m的整数倍,以保证在申请连续存储空间时各元素也按m字节对齐。

__attribute__((packed))

• 不按边界对齐,称为紧凑方式。

### C++ 中的数据对齐概念 在 C++ 编程语言中,数据对齐是指编译器为了提高访问速度而按照特定规则安排对象在内存中的位置。对于不同类型的变量,编译器会根据其自然边界来决定如何放置这些变量,从而使得 CPU 可以更高效地读取和写入数据。 ### 数据对齐的规则 当定义一个结构体或者类时,其中成员变量之间的排列并非简单地按声明顺序连续占用内存空间;相反,由于存在字节填充现象,实际使用的总大小可能会大于各个字段所需的空间之和。具体来说: - **最大成员对齐值**:结构体内最大的基本类型决定了该结构的整体对齐方式。例如,在给定的例子 `class A` 中含有 `_a(double)` 和静态成员 `_b(int)` ,因为 double 类型通常需要 8 字节对齐[^1]。 - **成员间对齐调整**:如果当前偏移量不是下一个待加入元素所需的最小对齐单位,则会在两者之间插入适当数量的未命名位域(即所谓的“空洞”),直到满足条件为止。 - **整体尺寸扩展至最严格对齐倍数**:最终计算出来的结构体或类实例所占的实际字节数目会被向上舍入到等于或超过所有内部组件中最严格的那个对齐需求的一个整数值上。 ```cpp #include <iostream> using namespace std; class A { public: void Print() { cout << "Print()" << endl; } private: double _a; static int _b; }; int main() { cout << sizeof(A) << endl; // 输出结果为 8 return 0; } ``` 上述代码展示了类 `A` 的布局情况。这里需要注意的是,尽管有一个静态成员 `_b` 存在于类定义里,但它并不会影响单个对象占据多少内存,因为它只有一份副本存放在全局区域而非每个实例之中。 ### 如何控制数据对齐行为 有时开发者可能希望改变默认的行为模式,这时可以利用一些预处理器指令或是属性来进行自定义设置: - 使用 `#pragma pack(n)` 来指定新的打包级别 n (n=1,2,4,8 或者 16),这会影响之后遇到的所有结构体/联合体直至遇见另一个同名命令恢复原状; - 应用 GNU 扩展关键字 `__attribute__((aligned(N)))` 给某个特定类型加上额外约束 N 表示期望达到至少多宽的边界; - Microsoft Visual Studio 提供了类似的特性通过附加说明符 `[align(value)]` 完成相似功能。 以上手段允许程序员更加灵活地管理程序内的资源分布状况,特别是在嵌入式开发领域显得尤为重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值