iOS底層探索(二)字節對齊

什麼是字節對齊

現代計算機中內存空間都是按照byte劃分的,從理論上講彷佛對任何類型的變量的訪問能夠從任何地址開始,但實際狀況是在訪問特定類型變量的時候常常在特 定的內存地址訪問,這就須要各類類型數據按照必定的規則在空間上排列,而不是順序的一個接一個的排放,這就是對齊。bash

做用和緣由

簡單來說是由CPU架構形成的。好比arm64(ARM)x86(Intel、AMD), PowerPC(IBM)等。 做爲iOS Developer,常見的有armv7armv7sarm64earm64i386x86_64。 CPU爲了高效執行指令或者讀取數據,不是按照字節讀取的,而是根據數據將內存分塊,每塊的字節數都是偶數,如 24816字節。每次讀取都是一個固定的開銷,減小內存存取次數將提高程序的性能。架構

  • 平臺緣由(移植緣由):不是全部的硬件平臺都能訪問任意地址上的任意數據,某些硬件平臺只能在某些地址處取某些特定類型的數據,不然拋出硬件異常。
  • 硬件緣由:通過內存對齊以後,CPU的內存訪問速度大大提高。

iOS的內存對齊

每一個特定的平臺上的編譯器都有本身的默認對齊係數(也叫對齊模數)。咱們能夠經過預編譯命令#pragma pack(n),n=1,2,4,8,16來改變這一系數,其中的n就是要指定的對齊係數。Xcode的對齊係數就是8,GCC對齊係數是4性能

對齊原則

咱們在瞭解內存對齊以前,先看看內存對齊的原則:spa

  • 數據成員對齊規則:
    Struct 或 union 的數據成員第一個數據成員放在偏移爲0的位置,之後每一個成員的偏移爲 min(對齊係數,自身長度)的整數倍,不夠整數倍的補齊。
  • 數據成員爲結構體:
    該數據成員的自身長度爲其最大長度的整數倍開始存儲
  • 總體對齊規則:
    數據成員按照上述規則對齊以後,其自己也要對齊,對齊原則是min(對其係數,成員最大長度)的整數倍。

翻譯一下就是翻譯

  • 前面的地址必須是後面的地址整數倍,不是就補齊
  • 結構體裏面的嵌套結構體大小要是該嵌套結構體最大元素大小的整數倍
  • 整個Struct的地址必須是最大字節的整數倍

代碼求源

接下來,須要用代碼驗證、查看對象alloc時開闢的真實空間具體是多少。
能夠用class_getInstanceSize(class)malloc_size()來打印出對象的大小。code

struct StructOne {
    char a;         //1字節
    double b;       //8字節
    int c;          //4字節
    short d;        //2字節
} MyStruct1;

struct StructTwo {
    double b;       //8字節
    char a;         //1字節
    short d;        //2字節
    int c;         //4字節
} MyStruct2;
NSLog(@"%lu---%lu", sizeof(MyStruct1), sizeof(MyStruct2));
複製代碼

獲得的結果是24---16對象

StructOne

  • a爲1字節,不夠8個字節,而第二個成員爲b爲double類型,爲8個字節,因此b能夠被編譯器單獨讀取,爲了讀取效率,不能夠分割也不能和其餘數據合併,因此要對a進行7個字節補充,使其佔用8個字節。
  • c爲int類型,佔用4個字節,d爲short類型,佔用2個字節,c和d能夠合併另外再對其進行2個字節的補充,使其佔用8個字節。 這樣就符合了內存對其原則,最後StructOne佔用的空間爲(1+7)+8+(4+2+2)=24。

StructTwo

  • b佔用8個字節
  • a、d、c能夠合併,再補充1個字節,使其佔用8個字節 最後StructTwo佔用的空間爲8+(1+2+4+1)=16。

總結

字節對齊是爲了提高CPU執行效率產生的規則,原理是按照對齊係數對內存進行排列讀取。在iOS中編譯器幫咱們處理了這一問題,因此無需考慮,但在平常開發中若是在寫C語言的代碼時,就能夠利用字節對齊的規則進行生命變量,以提高效率。內存

相關文章
相關標籤/搜索