關於VC,GCC成員變數的記憶體對齊和偏移量的問題

2021-06-08 14:10:32 字數 2286 閱讀 6387

vc中是這樣定義的

注意新增標頭檔案#include

/* define offsetof macro */

#ifdef __cplusplus

#ifdef _win64

#define offsetof(s,m) (size_t)( (ptrdiff_t)&reinterpret_cast((((s *)0)->m)) )

#else

#define offsetof(s,m) (size_t)&reinterpret_cast((((s *)0)->m))

#endif

#else

#ifdef _win64

#define offsetof(s,m) (size_t)( (ptrdiff_t)&(((s *)0)->m) )

#else

#define offsetof(s,m) (size_t)&(((s *)0)->m)

#endif

#endif /* __cplusplus */

稍後推出記憶體對齊的內容:

vc下:

我記得沒錯的話是:

struct tttmp;

這裡的所謂的最寬基本型別成員的意思不是說這個成員佔記憶體的大小,比如char a[7]的最寬基本型別成員的大小為1,int a的最寬基本型別成員大小為4,而稍微複雜的結構體則同樣以結構體裡的最寬基本型別成員的大小為準,例如下面的結構體,在vc下是8,在gcc下是4(為什麼是4的原因後面解釋)

struct {

int a;

char b;

double c;

這裡的成員p,從0開始,佔位1,分別為,0

這裡的成員a,從1開始,佔位8,由於必須是double最大位寬(8)的倍數,所以調整到8,所以佔記憶體位置為8,9,10,11,12,13,14,15

這裡的成員b,偏移量接在double a的後面,第16個位置,16是char 的整數倍,所以b就放在16的位置,佔記憶體位為16

這裡的成員c,偏移量從17開始,但是17不是shart的整數倍,所以填充空字元重新調整到18的位置,所以c放在18的偏移位址上,佔2個字元位,分別為18,19

這裡的成員d,偏移位置從20開始,是char的整數倍,所以直接開始寫資料,佔據5個字元位,分別是20,21,22,23,24,

這裡的成員e,偏移位置從25開始,是char的整數倍,所以直接開始寫資料,佔據4個字元位,分別是25,26,27,28,

綜上所述,總共佔記憶體29個(0到28), 

3:再然後查詢最大的記憶體對齊模數,這裡的結構體中是8

然後要求最後的大小必須是8的倍數,即8 16 24 32等

由於這條規則,需要是最大記憶體對齊模數的整數倍,也就是32,所以最後的sizeof(tt)即為32。

當然我上面說的全是vc下的對齊結果。

gcc下:

基本上和上面的步驟相似,但不同的地方是

而在gnu gcc編譯器中,遵循的準則有些區別,對齊模數不是像上面所述的那樣,根據最寬的基本資料型別來定。在gcc中,對齊模數的準則是:對齊模數最大只能是 4,也就是說,即使結構體中有double型別,對齊模數還是4,所以對齊模數只能是1,2,4。而且在上述的三條中,第2條裡,offset必須是成員大小的整數倍,如果這個成員大小小於等於4則按照上述準則進行,但是如果大於4了,則結構體每個成員相對於結構體首位址的偏移量(offset)只能按照是4的整數倍來進行判斷是否新增填充。

所以這裡的步驟是這樣的:

這裡的成員p,從0開始,佔位1,分別為,0

這裡的成員a,從1開始,佔位8,由於double的位寬》4,由於gcc的準則原因,對齊模數調整到4,所以佔位調整到4,所以佔記憶體位置為4,5,6,7,8,9,10,11

這裡的成員b,偏移量接在double a的後面,第12個位置,12是char 的整數倍,所以b就放在12的位置,佔記憶體位為12

這裡的成員c,偏移量從13開始,但是13不是shart的整數倍,所以填充空字元重新調整到14的位置,所以c放在14的偏移位址上,佔2個字元位,分別為14,15

這裡的成員d,偏移位置從16開始,是char的整數倍,所以直接開始寫資料,佔據5個字元位,分別是16,17,18,19,20,

這裡的成員e,偏移位置從21開始,是char的整數倍,所以直接開始寫資料,佔據4個字元位,分別是21,22,23,24

綜上所述,總共佔記憶體25個(0到24), 

然後要求最大的記憶體需要時對齊模數的整數倍,而由於double的存在,導致最大記憶體模數為4,所以最後的sizeof(tt)即為28。

通過例子應該明白很多了。這樣應該能看明白了吧。。。

成員變數記憶體分析

分析清楚記憶體,對 的執行更加的清楚 對以下簡單的 的記憶體分析.package com.object.test1 import com.object.object.person 載入進方法區 public class test1 方法出棧 有參構造 public person int age,st...

成員變數和成員函式記憶體分配

在c 中,成員變數和成員函式分開儲存,只有非靜態成員變數才屬於類的物件上。非靜態成員函式,靜態成員函式,靜態成員變數占用的記憶體均不占用類的物件空間上。示例1 include include using namespace std class person 非靜態成員函式 不屬於類的物件上 stat...

關於屬性,成員變數的認識

關於屬性和成員變數概念的說法,網上搜了很多,沒找到特別明確的說,而且還更加混亂了。根據自己的認識和從網上搜尋的資訊稍微總結一下 看法1 從訪問許可權上區分 屬性和成員變數說到底都是變數,只是他們的訪問許可權不同。在.h檔案的 中宣告的變數,預設是protect 在.m檔案的inte ce 宣告的變數...