C++11 記憶體對齊 alignof alignas
阿新 • • 發佈:2018-11-07
一 現象
先看一段程式碼:
struct s1 { char s; int i; }; struct s2 { int i; double d; }; cout << "-------basic type" << endl; cout << "sizeof(char) " << sizeof(char) << endl; cout << "sizeof(int) " << sizeof(int) << endl; cout << "sizeof(double) " << sizeof(double) << endl; cout << endl; cout << "-------struct" << endl; cout << "sizeof(s1) " << sizeof(s1) << endl; cout << "sizeof(s2) " << sizeof(s2) << endl;
結果如下:
不同機器環境,可能結果不同,但不影響說明問題。例如,結構體s1中包含一個char和int,那麼s1的大小應該是5,但結果是8,s2也是如此,這就涉及到一個概念:記憶體對齊。
二 記憶體對齊
1 什麼是記憶體對齊?
看到的一句說明,“資料項僅僅能儲存在地址是資料項大小的整數倍的記憶體位置上”。
2 為什麼要記憶體對齊?
(1)硬體原因,一些硬體平臺必須要求記憶體對齊,否則丟擲異常;另外涉及到不同平臺的移植問題。
(2)效能原因,對齊後訪問效率更高。
三 C++11 記憶體對齊實現
1 C++11 新引入操作符alignof, 對齊描述符alignas
alignas可以接受常量表達式和型別作為引數,可以修飾變數、類的資料成員等,不能修飾位域和用register申明的變數。一般往大對齊。
直接看一段程式碼(結合上一段程式碼):
struct s3 { char s; double d; int i; }; struct s11 { alignas(16) char s; int i; }; struct s12 { alignas(16) char s; int i; }; // alignof cout << "-------------------alignof---------------------" << endl; // 基本對齊值 cout << "alignof(std::max_align_t) " << alignof(std::max_align_t) << endl; cout << endl; cout << "-------basic type" << endl; cout << "alignof(char) " << alignof(char) << endl; cout << "alignof(int) " << alignof(int) << endl; cout << "alignof(double) " << alignof(double) << endl; cout << endl; cout << "-------struct" << endl; cout << "alignof(s1) " << alignof(s1) << endl; cout << "alignof(s2) " << alignof(s2) << endl; cout << "alignof(s3) " << alignof(s3) << endl; cout << endl; cout << endl; // alignas cout << "-------------------alignas---------------------" << endl; cout << "alignof(s1) " << alignof(s1) << endl; cout << "alignof(s11) " << alignof(s11) << endl; cout << "alignof(s12) " << alignof(s12) << endl; cout << "sizeof(s1) " << sizeof(s1) << endl; cout << "sizeof(s11) " << sizeof(s11) << endl; cout << "sizeof(s12) " << sizeof(s12) << endl;
結果如下:
2 C++11還新增了幾個記憶體對齊的函式,每個函式有特定作用,此處不展開。
std::alignment_of
std::aligned_storage
std::max_align_t
std::align
四 C++98/03 記憶體對齊實現
此情況下主要是由編譯器實現,不同編譯器有不同方法。
1 MSVC
__declspec(align(#)),其#的內容可以是預編譯巨集,但不能是編譯期數值
#progma pack
__alignof
2 gcc
__attribute__((__aligned__((#))))
__alignof__