背景:在任務中遇到了由於記憶體對齊引起的乙個double資料讀取錯誤問題,排查很久才發現偏移位址跑了4位。
記憶體對齊知識整理:
1、乙個對齊的例子:
struct struct1
;
2、記憶體對齊的好處:
簡單來說,是為了提高處理器對於資料的處理效率。
這裡涉及乙個概念:cpu的記憶體訪問粒度。目前的訪問粒度都是4位元組,也就是說cpu讀取資料的起始偏移位址永遠是4的整數倍。而我們常見的int型、double、long等佔位元組數較多的資料型別都是4的整數倍的位元組占用,因此,如果這類資料的起始位址是4的整數倍,cpu就可以以最小的代價獲取到資料,不用多進行一次資料訪問然後再進行兩次查詢結果的拼接。
因此,c++語言在執行編譯的時候自動對資料結構裡的資料執行了對齊操作,加快執行效率。
具體的,
資料型別對齊:(由於cpu訪問粒度為4,大於4個位元組的資料型別的對齊即為不小於自身大小的4的整數倍)型別
對齊值(位元組)
char
short
intfloat
double
類資料對齊:
使用成員當中最大的對齊位元組來對齊。比如在struct a中,int a的對齊位元組為4,比char,short都大,所以a的對齊位元組為4
指定對齊位元組:
巨集 #pragma pack(n)來指定的對齊值(後續有詳細使用方法)
有效對齊位元組值:
有效對齊位元組=min(自身對齊位元組, 指定對齊位元組值)
可以隨時使用sizeof運算子來計算此時的結構體大小來確認對齊情況。
3、如何調整對齊規則:
有時候,面對傳輸過來的資料,我們需要建立結構體來解析資料,如果資料本身沒有按照我們這邊的對齊方式來仿製資料就會讀取錯誤。
方法為:
#progma pack(n) // n = 1, 2, 4, 8
這個設定是全域性的,如果只是修改某個結構的對齊方式,需要加入巨集堆疊概念:
#progma pack(push)
#progma pack(1)
...#progma pack(pop)
舉例:
#pragma pack(push)
#pragma pack(1)
struct tfileheadinfo
;#pragma pack(pop)
也可以寫作:
#pragma pack(push, 1)
...#pragma pack(pop)
其他: C 記憶體對齊
vc6.0編譯器對記憶體對齊的管理方式遵循以下兩個原則 1.對於結構體內部變數的對齊方式 變數存放的起始位址相對於結構的起始位址的偏移量 char 偏移量必須為sizeof char 即1的倍數 int 偏移量必須為sizeof int 即4的倍數 float 偏移量必須為sizeof float ...
c 記憶體對齊
一.計算struct的size有兩個原則 pragma pack n n是編譯器的對齊位元組數 1 struct中各成員按照對齊原則 在為當前變數 設為a 分配記憶體時,要參考之前所有變數的偏移量之和 設為d d必須是min n,sizeof a 的倍數,否則編譯器會自動在最後補上缺少的位元組數。2...
C 記憶體對齊
c 中的記憶體對齊 記憶體對齊 在我們的程式中,資料結構還有變數等等都需要占有記憶體,在很多系統中,它都要求記憶體分配的時候要對齊,這樣做的好處就是可以提高訪問記憶體的速度。我們還是先來看一段簡單的程式 程式一 1 include 2 using namespace std 3 4structx1 ...