我注意到,在c/C++中,很多Win32 API結構需要被告知它們有多大。 即someStruct.pbFormat = sizeof(SomeStruct)
爲什麼結構需要被告知它們有多大?
爲什麼會出現這種情況?這是出於遺留原因嗎?還有什麼想法什麼「pb」也代表?
編輯:哎呀,是的,我的意思是「cbFormat」
我注意到,在c/C++中,很多Win32 API結構需要被告知它們有多大。 即someStruct.pbFormat = sizeof(SomeStruct)
爲什麼結構需要被告知它們有多大?
爲什麼會出現這種情況?這是出於遺留原因嗎?還有什麼想法什麼「pb」也代表?
編輯:哎呀,是的,我的意思是「cbFormat」
這是爲了向後兼容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
實現可以檢查大小,並決定「這個可憐的傢伙還不知道所有新功能」。
這是使結構可以在API的未來版本進行擴展,然後Windows可以知道(通過調用者傳遞的尺寸),該場應該被看着或不看。這基本上是API版本的一種粗略形式。
通常這些計數字節的前綴爲cb
,它代表「字節數」。例如,STARTUPINFO
結構開始於:
typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
...
} STARTUPINFO, *LPSTARTUPINFO;
將其在某些點與所述STARTUPINFOEX
結構,它包含相同的第一部分,但具有不同的尺寸延伸。根據cb
的值,Windows將知道是否查看新的lpAttributeList
字段。
其他主要操作系統是否採用這種方式進行API版本控制,還是有更好的替代方案? – MusiGenesis 2010-05-31 01:56:23
@MusiGenesis:很好的問題,問它:) – MSalters 2010-05-31 08:50:35
所以,未來的版本中可以添加額外的領域,仍然能夠提供向後二進制兼容性:
// 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
}
實際上它不能因包裝規則而失敗,因爲那些是由Win32隱含的。 – MSalters 2010-05-31 08:52:37
@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
根據Win32規則,這不是定義'struct foo'版本2的有效方法。設置爲sizeof(object)的第一個DWORD必須在v1和v2之間有所不同。 – MSalters 2010-06-01 07:49:31
的PB是Hungarian Notation一個例子,基本上是編碼可變型到其名稱的方案。
我相信這個問題並不針對命名約定 – YeenFei 2010-05-31 01:47:45
雖然這是匈牙利符號的主要問題的一個很好的附帶說明:如果你開始依靠這些小字母來實際*意思*重要的東西,那麼你遇到了麻煩。 – MusiGenesis 2010-05-31 01:58:19
實際上,兩個字符'cb'表示您的IDE不會:字節數。 – CMircea 2010-05-31 03:22:29
因爲Win32 API是一個C API - 不是C++,所以擴展API的面向對象方法不可用。使用C++ API,新功能將使用從舊版本衍生而來的結構,並調用採用基本結構的接口,確保類型安全。
C是一種程序性語言,並且在結構中可以做的事更有限。
+1應該有一個網站致力於人們認爲Windows吸收的理由,以及理性的,合理的解釋(比如這個),爲什麼某些事情是以某種方式完成的。有趣的是,向後兼容性往往是對Windows中其他奇怪事物的解釋 - 我通過提醒他們所有的軟件如何停止與每個新的操作系統一起工作,來使用它來安置Mac迷。 – MusiGenesis 2010-05-31 01:54:38
有時他們使用大小或版本變量,有時他們會去somestructEx來指示額外或擴展。 – 2010-05-31 01:57:03
@MusiGenesis:我相信有這樣一個網站,它被稱爲[雷蒙德陳的博客](http://blogs.msdn.com/b/oldnewthing/)。 :-) – 2010-05-31 01:57:35