我注意到在c / c ++中需要告诉很多Win32 API结构有多大。
即someStruct.pbFormat = sizeof(SomeStruct)
为什么会这样?它只是出于遗留原因吗?还有什么想法“pb”也代表什么?
编辑:哎呀,是的,我的意思是“cbFormat”答案 0 :(得分:12)
这是为了在扩展Windows API时实现向后兼容。
想象一下以下声明
struct WinData
{
long flags;
}
BOOL GetWinData(WinData * wd);
你这样称呼:
WinData wd;
GetWinData(&wd);
未来的操作系统版本可能会扩展到
struct WinData
{
long flags;
long extraData;
}
但是,如果您针对“较旧”的SDK编译,GetWinData
没有机会弄明白您不了解extraData
。如果它会填写它,它会覆盖堆栈上的数据。 BOOOM!
这就是为什么,将“调用者已知的大小”添加到结构中,并在末尾添加新成员。 GetWinData
实现可以检查大小并决定“这个可怜的家伙还不知道所有新功能”。
答案 1 :(得分:8)
这样可以在API的未来版本中扩展该结构,然后Windows可以知道(通过调用者传入的大小)应该查看哪些字段。它基本上是API版本的粗略形式。
通常这些计数字节以cb
为前缀,代表“字节数”。例如,STARTUPINFO
结构以:
typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
...
} STARTUPINFO, *LPSTARTUPINFO;
这在STARTUPINFOEX
结构的某些点延伸,其中包含相同的第一部分,但大小不同。根据{{1}}的值,Windows将知道是否要查看新的cb
字段。
答案 2 :(得分:1)
pb是Hungarian Notation的一个例子,基本上是一种将变量类型编码到其名称中的方案。
答案 3 :(得分:1)
由于Win32 API是 C API - 而不是C ++,因此无法使用面向对象的扩展API方法。使用C ++ API,新功能将使用从旧版本派生的结构并调用采用基本结构的接口,从而确保类型安全。
C是一种程序性语言,对结构的处理方式更为有限。
答案 4 :(得分: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
}