为什么需要告诉结构它们有多大?

时间:2010-05-31 01:11:23

标签: c++ c struct sizeof

我注意到在c / c ++中需要告诉很多Win32 API结构有多大。 即someStruct.pbFormat = sizeof(SomeStruct)

为什么会这样?它只是出于遗留原因吗?还有什么想法“pb”也代表什么?

编辑:哎呀,是的,我的意思是“cbFormat”

5 个答案:

答案 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
}