<commit_before>---
layout:     post
title:      "内存对齐"
subtitle:   ""
date:       2017-06-11
author:     "Darcy"
header-img: ""
tags:
- Pattern
image:
  feature: 
  teaser: work.jpg
  credit: Death to Stock Photo
  creditlink: ""
---

对齐：现代计算机中内存空间都是按照 `byte` 划分的，从理论上讲似乎对任何类型的变量的访问可以从任何地址开始，但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问， 这就需要各种类型数据按照一定的规则在空间上排列，而不是顺序的一个接一个的排放。

<!--more-->

## 对齐原因

- 平台移植：各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的 `CPU` 在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐。

- 性能原因：有些平台每次读都是从偶地址开始，如果一个 `int` 型（假设为32位系统）如果存放在偶地址开始的地方，那么一个读周期就可以读出这32 `bit` ，而如果存放在奇地址开始的地方，就需要2个读周期，并对两次读出的结果的高低字节进行拼凑才能得到该32 `bit` 数据。显然在读取效率上下降很多。

## 对齐规则

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。我们可以通过预编译命令`#pragma pack(n)`，n = 1,2,4,8,16 来改变这一系数，其中的  `n`  就是你要指定的“对齐系数”。

- 数据成员对齐规则：结构 (`struct` ）（或联合(  `union`  ））的数据成员，第一个数据成员放在  `offset` 为0 的地方，以后每个数据成员的对齐按照  `#pragma pack` 指定的数值和这个数据成员自身长度中，比较小的那个进行。
- 结构（或联合）的整体对齐规则：在数据成员完成各自对齐之后，结构（或联合）本身也要进行对齐，对齐将按照 `#pragma pack` 指定的数值和结构（或联合）最大数据成员长度中，比较小的那个进行。
- 当 `#pragma pack` 的 `n` 值等于或超过所有数据成员长度的时候，这个 `n` 值的大小将不产生任何效果。

## 概念

- 数据类型自身的对齐值：64位机器上  `char` 型数据自身对齐值为1字节，`short` 型数据为2字节，`int/float` 型为4字节，`double` 型为8字节，指针为8字节。
- 结构体或类的自身对齐值：其成员中自身对齐值最大的那个值。
- 指定对齐值：`#pragma pack (value)` 时的指定对齐值 `value`。
- 数据成员、结构体和类的有效对齐值：自身对齐值和指定对齐值中较小者，即有效对齐值 = `min` {自身对齐值，当前指定的 `pack` 值}。
<commit_msg>add alignment<commit_after>---
layout:     post
title:      "内存对齐"
subtitle:   ""
date:       2017-06-11
author:     "Darcy"
header-img: ""
tags:
- Pattern
image:
  feature: 
  teaser: walk.jpg
  credit: Death to Stock Photo
  creditlink: ""
---

对齐：现代计算机中内存空间都是按照 `byte` 划分的，从理论上讲似乎对任何类型的变量的访问可以从任何地址开始，但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问， 这就需要各种类型数据按照一定的规则在空间上排列，而不是顺序的一个接一个的排放。

<!--more-->

## 对齐原因

- 平台移植：各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的 `CPU` 在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐。

- 性能原因：有些平台每次读都是从偶地址开始，如果一个 `int` 型（假设为32位系统）如果存放在偶地址开始的地方，那么一个读周期就可以读出这32 `bit` ，而如果存放在奇地址开始的地方，就需要2个读周期，并对两次读出的结果的高低字节进行拼凑才能得到该32 `bit` 数据。显然在读取效率上下降很多。

## 对齐规则

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。我们可以通过预编译命令`#pragma pack(n)`，n = 1,2,4,8,16 来改变这一系数，其中的  `n`  就是你要指定的“对齐系数”。

- 数据成员对齐规则：结构 (`struct` ）（或联合(  `union`  ））的数据成员，第一个数据成员放在  `offset` 为0 的地方，以后每个数据成员的对齐按照  `#pragma pack` 指定的数值和这个数据成员自身长度中，比较小的那个进行。
- 结构（或联合）的整体对齐规则：在数据成员完成各自对齐之后，结构（或联合）本身也要进行对齐，对齐将按照 `#pragma pack` 指定的数值和结构（或联合）最大数据成员长度中，比较小的那个进行。
- 当 `#pragma pack` 的 `n` 值等于或超过所有数据成员长度的时候，这个 `n` 值的大小将不产生任何效果。

## 概念

- 数据类型自身的对齐值：64位机器上  `char` 型数据自身对齐值为1字节，`short` 型数据为2字节，`int/float` 型为4字节，`double` 型为8字节，指针为8字节。
- 结构体或类的自身对齐值：其成员中自身对齐值最大的那个值。
- 指定对齐值：`#pragma pack (value)` 时的指定对齐值 `value`。
- 数据成员、结构体和类的有效对齐值：自身对齐值和指定对齐值中较小者，即有效对齐值 = `min` {自身对齐值，当前指定的 `pack` 值}。

{'fraction_non_alphanumeric': 0.142433234421365, 'fraction_numerical': 0.021513353115727003, 'mean_word_length': 6.533519553072626, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2472982', 'n_tokens_mistral': 2104, 'n_tokens_neox': 2459, 'n_words': 175}