/*
在最近的項目中,我們涉及到了“內(nèi)存對齊”技術(shù)。對于大部分程序員來說,“內(nèi)存對齊”對他們來說都應(yīng)該是“透明的”。“內(nèi)存 對齊”應(yīng)該是編譯器的“管轄范圍”。編譯器為程序中的每個“數(shù)據(jù)單元”安排在適當?shù)奈恢蒙?。但是C語言的一個特點就是太靈活
,太強大,它允許你干預(yù)“內(nèi)存對齊”。如果你想了解更加底層的秘密,“內(nèi)存對齊”對你就不應(yīng)該再透明了。 一、內(nèi)存對齊
的原因
內(nèi)存對齊(3張) 大部分的參考資料都是如是說的: 1、平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任 意數(shù)據(jù)的;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。 2、性能原因:數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)
該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問;而對齊的內(nèi)存訪問僅需要一次訪問
。 二、對齊規(guī)則 每個特定平臺上的編譯器都有自己的默認“對齊系數(shù)”(也叫對齊模數(shù))。程序員可以通過預(yù)編譯命令
#pragma pack(n),n=1,2,4,8,16來改變這一系數(shù),其中的n就是你要指定的“對齊系數(shù)”。 規(guī)則: 1、數(shù)據(jù)成員對齊規(guī)則
:結(jié)構(gòu)(struct)(或聯(lián)合(union))的數(shù)據(jù)成員,第一個數(shù)據(jù)成員放在offset為0的地方,以后每個數(shù)據(jù)成員的對齊按照#pragma pack指
定的數(shù)值和這個數(shù)據(jù)成員自身長度中,比較小的那個進行。 2、結(jié)構(gòu)(或聯(lián)合)的整體對齊規(guī)則:在數(shù)據(jù)成員完成各自對齊之后,
結(jié)構(gòu)(或聯(lián)合)本身也要進行對齊,對齊將按照#pragma pack指定的數(shù)值和結(jié)構(gòu)(或聯(lián)合)最大數(shù)據(jù)成員長度中,比較小的那個進行。
3、結(jié)合1、2可推斷:當#pragma pack的n值等于或超過所有數(shù)據(jù)成員長度的時候,這個n值的大小將不產(chǎn)生任何效果。
Win32平臺下的微軟C編譯器(cl.exe for 80×86)的對齊策略: 1) 結(jié)構(gòu)體變量的首地址是其最長基本類型成員的整數(shù)倍;
備注:編譯器在給結(jié)構(gòu)體開辟空間時,首先找到結(jié)構(gòu)體中最寬的基本數(shù)據(jù)類型,然后尋找內(nèi)存地址能是該基本數(shù)據(jù)類型的整倍的位置
,作為結(jié)構(gòu)體的首地址。將這個最寬的基本數(shù)據(jù)類型的大小作為上面介紹的對齊模數(shù)。 2) 結(jié)構(gòu)體每個成員相對于結(jié)構(gòu)體首地址
的偏移量(offset)都是成員大小的整數(shù)倍,如有需要編譯器會在成員之間加上填充字節(jié)(internal adding); 備注:為結(jié)構(gòu)
體的一個成員開辟空間之前,編譯器首先檢查預(yù)開辟空間的首地址相對于結(jié)構(gòu)體首地址的偏移是否是本成員的整數(shù)倍,若是,則存放
本成員,反之,則在本成員和上一個成員之間填充一定的字節(jié),以達到整數(shù)倍的要求,也就是將預(yù)開辟空間的首地址后移幾個字節(jié)。
3) 結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本類型成員大小的整數(shù)倍,如有需要,編譯器會在最末一個成員之后加上填充字節(jié)
(trailing padding)。 備注:結(jié)構(gòu)體總大小是包括填充字節(jié),最后一個成員滿足上面兩條以外,還必須滿足第三條,否則就
必須在最后填充幾個字節(jié)以達到本條要求。 4) 結(jié)構(gòu)體內(nèi)類型相同的連續(xù)元素將在連續(xù)的空間內(nèi),和數(shù)組一樣。 5) 如果結(jié)
構(gòu)體內(nèi)存在長度大于處理器位數(shù)的元素,那么就以處理器的倍數(shù)為對齊單位;否則,如果結(jié)構(gòu)體內(nèi)的元素的長度都小于處理器的倍數(shù)
的時候,便以結(jié)構(gòu)體里面最長的數(shù)據(jù)元素為對齊單位。
*/ #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
} 最近在練習使用函數(shù)模板,在func.h定義了一個函數(shù)
我把函數(shù)模板的具體實現(xiàn)放在了func.cpp里
在main.cpp里面包含func.h, 然后調(diào)用functionA(obj) 編譯各個文件都沒問題,最后link的時候居然報告 functionA<ObjectType>(ObjectType) 找不到。 是不是函數(shù)模板的實現(xiàn)(我現(xiàn)在放在func.cpp的部分)必須放在func.h里面不然這個函數(shù)模板根本就沒有實例化?我自己感覺是這樣,但是不確定是不是,還望指點,謝謝! 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;
|
|