/*
在最近的項目中,我們涉及到了“內存對齊”技術(shù)。對于大部分程序員來(lái)說(shuō),“內存對齊”對他們來(lái)說(shuō)都應該是“透明的”。“內存
對齊”應該是編譯器的“管轄范圍”。編譯器為程序中的每個(gè)“數據單元”安排在適當的位置上。但是C語(yǔ)言的一個(gè)特點(diǎn)就是太靈活
,太強大,它允許你干預“內存對齊”。如果你想了解更加底層的秘密,“內存對齊”對你就不應該再透明了。 一、內存對齊
的原因
內存對齊(3張) 大部分的參考資料都是如是說(shuō)的: 1、平臺原因(移植原因):不是所有的硬件平臺都能訪(fǎng)問(wèn)任意地址上的任
意數據的;某些硬件平臺只能在某些地址處取某些特定類(lèi)型的數據,否則拋出硬件異常。 2、性能原因:數據結構(尤其是棧)應
該盡可能地在自然邊界上對齊。原因在于,為了訪(fǎng)問(wèn)未對齊的內存,處理器需要作兩次內存訪(fǎng)問(wèn);而對齊的內存訪(fǎng)問(wèn)僅需要一次訪(fǎng)問(wèn)
。 二、對齊規則 每個(gè)特定平臺上的編譯器都有自己的默認“對齊系數”(也叫對齊模數)。程序員可以通過(guò)預編譯命令
#pragma pack(n),n=1,2,4,8,16來(lái)改變這一系數,其中的n就是你要指定的“對齊系數”。 規則: 1、數據成員對齊規則
:結構(struct)(或聯(lián)合(union))的數據成員,第一個(gè)數據成員放在offset為0的地方,以后每個(gè)數據成員的對齊按照#pragma pack指
定的數值和這個(gè)數據成員自身長(cháng)度中,比較小的那個(gè)進(jìn)行。 2、結構(或聯(lián)合)的整體對齊規則:在數據成員完成各自對齊之后,
結構(或聯(lián)合)本身也要進(jìn)行對齊,對齊將按照#pragma pack指定的數值和結構(或聯(lián)合)最大數據成員長(cháng)度中,比較小的那個(gè)進(jìn)行。
3、結合1、2可推斷:當#pragma pack的n值等于或超過(guò)所有數據成員長(cháng)度的時(shí)候,這個(gè)n值的大小將不產(chǎn)生任何效果。
Win32平臺下的微軟C編譯器(cl.exe for 80×86)的對齊策略: 1) 結構體變量的首地址是其最長(cháng)基本類(lèi)型成員的整數倍;
備注:編譯器在給結構體開(kāi)辟空間時(shí),首先找到結構體中最寬的基本數據類(lèi)型,然后尋找內存地址能是該基本數據類(lèi)型的整倍的位置
,作為結構體的首地址。將這個(gè)最寬的基本數據類(lèi)型的大小作為上面介紹的對齊模數。 2) 結構體每個(gè)成員相對于結構體首地址
的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會(huì )在成員之間加上填充字節(internal adding); 備注:為結構
體的一個(gè)成員開(kāi)辟空間之前,編譯器首先檢查預開(kāi)辟空間的首地址相對于結構體首地址的偏移是否是本成員的整數倍,若是,則存放
本成員,反之,則在本成員和上一個(gè)成員之間填充一定的字節,以達到整數倍的要求,也就是將預開(kāi)辟空間的首地址后移幾個(gè)字節。
3) 結構體的總大小為結構體最寬基本類(lèi)型成員大小的整數倍,如有需要,編譯器會(huì )在最末一個(gè)成員之后加上填充字節
(trailing padding)。 備注:結構體總大小是包括填充字節,最后一個(gè)成員滿(mǎn)足上面兩條以外,還必須滿(mǎn)足第三條,否則就
必須在最后填充幾個(gè)字節以達到本條要求。 4) 結構體內類(lèi)型相同的連續元素將在連續的空間內,和數組一樣。 5) 如果結
構體內存在長(cháng)度大于處理器位數的元素,那么就以處理器的倍數為對齊單位;否則,如果結構體內的元素的長(cháng)度都小于處理器的倍數
的時(shí)候,便以結構體里面最長(cháng)的數據元素為對齊單位。
*/
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#endif
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if(p) { delete [] (p); (p)=NULL; } }
#endif
#pragma pack(1); // sizeof(t) = 13;
struct tag_test
{
int a;
char b;
short c;
char d[6];
tag_test()
{
a = 1;
b = 'c';
c = 1;
memset(d,'a',6);
}
};
template <class T>
void Swap(T &a, T &b)
{
T p ;
p = a;
a = b;
b = p;
}
void Fun(char *str)
{
int n = sizeof(str);//4
int m = sizeof(str[0]);//1
cout<<n<<endl;
cout<<m<<endl;
}
void main()
{
tag_test t;
int n = sizeof(t);
cout<<n<<endl;
int a = 1;
int b = 2;
cout<<a<<" "<<b<<endl;
Swap(a,b);
cout<<a<<" "<<b<<endl;
char *s = "abcde";
Fun(s);
int j = sizeof(s);// 4
int u = strlen(s);//5
int d = sizeof(s[0]);//1
cout<<j<<endl;
cout<<d<<endl;
cout<<u<<endl;
char r[10];
cout<<sizeof(r)<<endl;// 10
}
最近在練習使用函數模板,在func.h定義了一個(gè)函數
- template < typename T >
- bool functionA(T param);
復制代碼我把函數模板的具體實(shí)現放在了func.cpp里
- template < typename T >
- bool functionA(T param)
- {
- ....
- }
復制代碼在main.cpp里面包含func.h,
然后調用functionA(obj)
編譯各個(gè)
文件都沒(méi)問(wèn)題,最后link的時(shí)候居然報告
functionA<ObjectType>(ObjectType) 找不到。
是不是函數模板的實(shí)現(我現在放在func.cpp的部分)必須放在func.h里面不然這個(gè)函數模板根本就沒(méi)有實(shí)例化?我自己感覺(jué)是這樣,但是不確定是不是,還望指點(diǎn),謝謝!
struct tag_TPClipQualityInfo
{
TP_CLIP_QUALITY_TYPE eQualityType;
TP_CLIP_CLASS_TYPE eClipClass;
TPClipVAFormat stuClipVAFormat; //包含所有視音頻信息
long lSubIndex;
UINT uQualityState;
CString sDescription[TP_CLIP_FILE_MAX];
TP_CLIP_CLASS_TYPE eDBEClass;
CArray< _tagQualityItem2 *,_tagQualityItem2 *&> aQualityItem[TP_CLIP_FILE_MAX];
CArray< _tagGroupItem2 * ,_tagGroupItem2 *&> aGroupItem;
CArray< _tagQualityItem2 *,_tagQualityItem2 *&> aTemp;
tag_TPClipQualityInfo()
{
eQualityType = TP_CLIP_QUALITY_HIGH;
eClipClass = 0;
eDBEClass = 0;
uQualityState = 0;
lSubIndex = 0;
stuClipVAFormat.Reset();
for(INT l = 0; l < TP_CLIP_FILE_MAX; l++)
sDescription[l] = _T("");
}
~tag_TPClipQualityInfo()
{
ReleaseItem(FALSE);
Reset();
}
void ReleaseItem(BOOL bBegin)
{
for(INT l=0;l<aTemp.GetSize();l++)
{
if(aTemp[l] ->sDataFileName) delete [] aTemp[l] ->sDataFileName;aTemp[l] ->sDataFileName = NULL;
if(aTemp[l] ->sDataFilePath) delete [] aTemp[l] ->sDataFilePath;aTemp[l] ->sDataFilePath = NULL;
delete aTemp[l];
}
aTemp.RemoveAll();
}
void ReleaseGroupItem()
{
for(INT k=0;k<aGroupItem.GetSize();k++)
{
delete aGroupItem[k];
}
aGroupItem.RemoveAll();
}*m_paClipQualityInfo[TP_CLIP_QUALITY_MAX];
TCHAR sName[MAX_PATH];
stuTemplateData.sFileName = (LPTSTR)(LPCTSTR)sFileName;