//=====================================================================
//TITLE:
// 結構體等值的比較
//AUTHOR:
// norains
//DATE:
// Tuesday 19- January-2010
//Environment:
// WINDOWS
//=====================================================================
注:如果結構體内有填充值(PAD)的話,比較的結果會不正确。故本文所提的方法請慎重使用。
對于Windows下的開發,可能有不少人都會遇到這麼一個類似的問題:如何比較兩個RECT是否相等?因為RECT是一個結構體,很多人直覺是,重載==操作符。但重載==還是會涉及到一個關鍵點:如何判斷?
我們先簡單地以RECT作為例子。假設我們有一個函數,名為IsEqual,形參是兩個RECT。故函數原型是:
BOOL IsEqual(const RECT &rcVal1,const RECT &rcVal2)
當rcVal1和rcVal2相等時,傳回TRUE;否則,傳回FALSE。
也許最簡單的寫法,可能大家都會想到:
BOOL IsEqual(const RECT &rcVal1,const RECT &rcVal2)
{
if(rcVal1.left == rcVal2.left &&
rcVal1.right == rcVal2.right &&
rcVal1.bottom == rcVal2.bottom &&
rcVal1.top == rcVal2.top )
{
return TRUE;
}
else
{
return FALSE;
}
}
雖然這寫法思路簡單,但實在笨拙。如果形參不是RECT,而是别的成員變量暴多的結構體,比如ImageInfo這種,那麼這個if可就要寫得又臭又長了。無論是效率,還是可觀賞性,都不值一提。
其實我們可以換個角度,既然結構體可以借助memset來進行指派,那麼我們也可以通過memcmp來進行比較。是以,IsEqual函數可以更改如下:
BOOL IsEqual(const RECT &rcVal1,const RECT &rcVal2)
{
return (memcmp(reinterpret_cast<const VOID *>(&rcVal1),reinterpret_cast<const VOID *>(&rcVal2),sizeof(RECT)) == 0);
}
很簡單,隻是一個語句而已。因為結構體的成員變量是在一個連續的記憶體中,是以我們可以直接調用memcmp來比較兩者的記憶體資料是否一緻;而當兩個形參相等時,memcmp的傳回值為0。是以我們隻需要判斷傳回值是否為0,即可得出兩者是否相等。
對于RECT是可以判斷了,那麼SIZE,POINT諸如此類等等呢?難道每一個我們都寫一個IsEqual函數?還好,我們的C++還有模闆一說。為了适應于多種類型,則該函數可以更改如下:
template <class TYPE>
BOOL IsEqual(const TYPE &data1,const TYPE &data2)
{
return (memcmp(reinterpret_cast<const VOID *>(&data1),reinterpret_cast<const VOID *>(&data2),sizeof(TYPE)) == 0);
}
OK,現在無論是RECT,或是POINT,SIZE等等,凡是結構體類型,都可以調用該函數進行等值比較。
文章最後,可能會有疑問。既然比較函數隻是調用memcmp,為什麼還要大費周折披上一個IsEqual的皮呢?從意會角度而言,IsEqual是不是比memcmp更容易明白代碼所做的操作?更何況,memcmp相等時傳回的是0,我想有不少馬大哈可能直接就判斷傳回值是否等于FALSE,這恰好和函數本意相反。再說了,直接調用memcmp還要加上類型轉換的操作,還要多敲幾次鍵盤。既然如此,為何不讓它披一層簡單的皮呢?