1. 程式人生 > >資料結構:結構體在繼承中資料記憶體排列探究

資料結構:結構體在繼承中資料記憶體排列探究

下面以一個例子來說明(為了方便,結構體命名方面就馬虎點了):
#ifndef _STRUCTTEST_H_
#define _STRUCTTEST_H_

typedef struct tag_Base
{
	int s32Count;
	char byNone;
	bool bYes;
	long dwTemp;
	tag_Base()
	{
		s32Count = 100;
		byNone = 'Y';
		bYes = true;
		dwTemp = 200;
		printf("Base created!\n");
	};
}TBase;

typedef struct tag_Base2
{
	int s32Count;
	char byNone;
	long dwTemp;
	bool bYes;
	tag_Base2()
	{
		s32Count = 100;
		byNone = 'Y';
		bYes = true;
		dwTemp = 200;
		printf("Base2 created!\n");
	};
}TBase2;


typedef struct tag_InheritBase : public TBase
{
	char byIyes;
	int dwItemp;
	tag_InheritBase()
	{
		byIyes = '0';
		dwItemp = 1023;
		printf("Tinherit has been created!\n");
	}
}Tinherit;

typedef struct tag_InheritBase2 : public TBase2
{
	char byIyes;
	int dwItemp;
	tag_InheritBase2()
	{
		byIyes = '0';
		dwItemp = 1023;
		printf("Tinherit has been created!\n");
	}
}Tinherit2;

#endif // !_STRUCTTEST_H_

1. 在VS2013環境,編譯器為:MS VC++ 12.0

tag_Base結構體的大小是4+4+4 

以一次實驗資料舉例,其在記憶體中的儲存特性如下:

0x00A6FE74 |0x64 0x00 0x00 0x00   ##大端還是小端看的出來哦,
0x00A6FE78 |0x59 0x01 0xcc 0xcc    ##第二個4位元組,先存char然後在存的bool
0x00A6FE7C |0xc8 0x00 0x00 0x00

tag_Base2幾乎與TBase一樣,只是順序有點變動,所以佔的位元組數也就不同了(4+4+4+4)

同樣是一個例項,觀察其在記憶體中的排列:

0x0013F060 |0x64 0x00 0x00 0x00   
0x0013F064 |0x59 0xcd 0xcd 0xcd   
0x0013F068 |0xc8 0x00 0x00 0x00

0x0013F06C |0x01 0xcd 0xcd 0xcd   

對於結構體的繼承:

Tinherit繼承與TBase結構體,其佔用空間為20:

(4+4+4+4+4),以下為例項:

0x0111DAB8 |0x64 0x00 0x00 0x00  (int)
0x0111DABC |0x59 0x01 0xcd 0xcd  (char)(0x0111DABD|bool)
0x0111DAC0 |0xc8 0x00 0x00 0x00  (long)
0x0111DAC4 |0x30 0xcd 0xcd 0xcd  (char)

0x0111DAC8 |0xff 0x03 0xcd 0xcd  (int) 

Tinherit2繼承與TBase2結構體,其佔用空間為24:

(4+4+4+4+4+4),以下為例項:

0x00ABDAD0 |0x64 0x00 0x00 0x00  (int s32Count)
0x00ABDAD4 |0x59 0xcd 0xcd 0xcd  (char byNone)
0x00ABDAD8 |0xc8 0x00 0x00 0x00  (long dwTemp)
0x00ABDADC |0x01 0xcd 0xcd 0xcd  (bool bYes)
0x00ABDAE0  |0x30 0xcd 0xcd 0xcd  (char byIyes)

0x00ABDAE4  |0xff 0x03 0xcd 0xcd   (int dwItemp)

由此可見結構體的繼承中,其父結構體與子結構體在記憶體中的排列,是父類在前,子類在後,且在該種編譯環境下父類與子類不會採用緊湊排列方法。

2. 編譯器gcc version 3.4.6 20060404 (Red Hat 3.4.6-11)

本文同時嘗試過不同編譯器環境下,對資料結構的排列的影響。採用Linux系統下的G++編譯器,編譯器版本為gcc version 3.4.6 20060404 (Red Hat 3.4.6-11)實驗結果摒棄相同的部分,不同之處在於,對於Tinherit2結構體的排列,Linux系統採用了緊湊排列的方式,例項如下:0x9c54008  |0x64 0x00 0x00 0x00  (int s32Count)
0x9c5400C  |0x59 0xcd 0xcd 0xcd  (char byNone)
0x9c54010  |0xc8 0x00 0x00 0x00  (long dwTemp)
0x9c54014  |0x01 0x30 0xcd 0xcd  (bool bYes)(0x9c54015|char byIyes)
0x9c54018  |0xff 0x03 0xcd 0xcd  (int dwItemp)

結論:

1. 結構體的繼承中,父結構體的成員資料排在子結構體之前

2. 對於不同的平臺,結構體整體資料儲存優化類似,但是不同編譯器之間父與子的資料是否緊湊排列有所不同