2010-05-31 26 views
8

我注意到,在c/C++中,很多Win32 API結構需要被告知它們有多大。 即someStruct.pbFormat = sizeof(SomeStruct)爲什麼結構需要被告知它們有多大?

爲什麼會出現這種情況?這是出於遺留原因嗎?還有什麼想法什麼「pb」也代表?

編輯:哎呀,是的,我的意思是「cbFormat」

回答

12

這是爲了向後兼容Windows API擴展時。

想象一下下面的聲明

struct WinData 
{ 
    long flags; 
} 
BOOL GetWinData(WinData * wd); 

,你在呼喚這樣的:

WinData wd; 
GetWinData(&wd); 

未來的OS版本可能這個延伸到

struct WinData 
{ 
    long flags; 
    long extraData; 
} 

但是,如果你編譯對「較舊」的SDK,GetWinData沒有機會弄清楚你不知道約extraData。無論如何,它會覆蓋堆棧中的數據。 BOOOM!

這就是爲什麼「調用者已知的大小」被添加到結構中,新成員被添加到結尾。 GetWinData實現可以檢查大小,並決定「這個可憐的傢伙還不知道所有新功能」。

+2

+1應該有一個網站致力於人們認爲Windows吸收的理由,以及理性的,合理的解釋(比如這個),爲什麼某些事情是以某種方式完成的。有趣的是,向後兼容性往往是對Windows中其他奇怪事物的解釋 - 我通過提醒他們所有的軟件如何停止與每個新的操作系統一起工作,來使用它來安置Mac迷。 – MusiGenesis 2010-05-31 01:54:38

+0

有時他們使用大小或版本變量,有時他們會去somestructEx來指示額外或擴展。 – 2010-05-31 01:57:03

+11

@MusiGenesis:我相信有這樣一個網站,它被稱爲[雷蒙德陳的博客](http://blogs.msdn.com/b/oldnewthing/)。 :-) – 2010-05-31 01:57:35

8

這是使結構可以在API的未來版本進行擴展,然後Windows可以知道(通過調用者傳遞的尺寸),該場應該被看着或不看。這基本上是API版本的一種粗略形式。

通常這些計數字節的前綴爲cb,它代表「字節數」。例如,STARTUPINFO結構開始於:

typedef struct _STARTUPINFO { 
    DWORD cb; 
    LPTSTR lpReserved; 
    ... 
} STARTUPINFO, *LPSTARTUPINFO; 

將其在某些點與所述STARTUPINFOEX結構,它包含相同的第一部分,但具有不同的尺寸延伸。根據cb的值,Windows將知道是否查看新的lpAttributeList字段。

+2

其他主要操作系統是否採用這種方式進行API版本控制,還是有更好的替代方案? – MusiGenesis 2010-05-31 01:56:23

+0

@MusiGenesis:很好的問題,問它:) – MSalters 2010-05-31 08:50:35

0

所以,未來的版本中可以添加額外的領域,仍然能夠提供向後二進制兼容性:

// CAUTION - the code is not 100% accurate and can fail due to packing rules. 
// For illustrative purposes only 
if (offsetof(struct foo, field) > f->pbFormat) 
{ 
    // called with a version that predates the addition of 
    // field so revert to a default value 
} 
+0

實際上它不能因包裝規則而失敗,因爲那些是由Win32隱含的。 – MSalters 2010-05-31 08:52:37

+0

@MSalters - 不幸的是,它可能會失敗。考慮以'struct foo {int size;短s1; char c1; }'然後將其擴展爲'struct foo {int size;短s1; char c1; char c2; }'兩者的大小都是8,所以你不能判斷調用者是否有一個帶或不帶'c2'的定義。 – 2010-05-31 16:33:40

+0

根據Win32規則,這不是定義'struct foo'版本2的有效方法。設置爲sizeof(object)的第一個DWORD必須在v1和v2之間有所不同。 – MSalters 2010-06-01 07:49:31

1

的PB是Hungarian Notation一個例子,基本上是編碼可變型到其名稱的方案。

+0

我相信這個問題並不針對命名約定 – YeenFei 2010-05-31 01:47:45

+0

雖然這是匈牙利符號的主要問題的一個很好的附帶說明:如果你開始依靠這些小字母來實際*意思*重要的東西,那麼你遇到了麻煩。 – MusiGenesis 2010-05-31 01:58:19

+0

實際上,兩個字符'cb'表示您的IDE不會:字節數。 – CMircea 2010-05-31 03:22:29

1

因爲Win32 API是一個C API - 不是C++,所以擴展API的面向對象方法不可用。使用C++ API,新功能將使用從舊版本衍生而來的結構,並調用採用基本結構的接口,確保類型安全。

C是一種程序性語言,並且在結構中可以做的事更有限。

相關問題