天天看點

結構體等值的比較

//=====================================================================

//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還要加上類型轉換的操作,還要多敲幾次鍵盤。既然如此,為何不讓它披一層簡單的皮呢?

繼續閱讀