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

Gam*_*WTF 8 c c++ struct sizeof

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

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

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

pet*_*hen 12

这是为了在扩展Windows API时实现向后兼容.

想象一下以下声明

struct WinData
{
   long flags;
}
BOOL GetWinData(WinData * wd);
Run Code Online (Sandbox Code Playgroud)

你这样称呼的是:

WinData wd;
GetWinData(&wd);
Run Code Online (Sandbox Code Playgroud)

未来的操作系统版本可能会扩展到

struct WinData
{
   long flags;
   long extraData;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您已经针对"较旧"的SDK编译,GetWinData则没有机会弄清楚您不知道extraData.如果它会填写它,它会覆盖堆栈上的数据.BOOOM!

这就是为什么,"调用者已知的大小"被添加到结构中,并在末尾附加新成员.该GetWinData实施可以检查的大小和决定"这个可怜的家伙不知道所有的新功能呢."

  • @MusiGenesis:我相信有这样一个网站,它被称为[Raymond Chen的博客](http://blogs.msdn.com/b/oldnewthing/).:-) (11认同)
  • +1应该有一个专门用于人们认为Windows糟糕的原因的网站,以及为什么以某种方式完成某些事情的理性,合理的解释(比如这个).有趣的是,向后兼容性往往是对Windows中其他奇怪事物的解释 - 我有时会用它来劝说Mac粉丝,提醒他们所有软件如何停止使用每个新操作系统. (2认同)

Gre*_*ill 8

这样可以在API的未来版本中扩展该结构,然后Windows可以知道(通过调用者传入的大小)应该查看哪些字段.它基本上是API版本的粗略形式.

通常这些计数字节以前缀为前缀cb,代表"字节数".例如,STARTUPINFO结构以:

typedef struct _STARTUPINFO {
  DWORD  cb;
  LPTSTR lpReserved;
  ...
} STARTUPINFO, *LPSTARTUPINFO;
Run Code Online (Sandbox Code Playgroud)

这在某种程度上延伸了STARTUPINFOEX结构,其中包含相同的第一部分但具有不同的尺寸.根据值cb,Windows将知道是否查看新lpAttributeList字段.

  • 其他主要操作系统是否通过这种方式进行API版本控制,或者是否有更好的替代品? (2认同)