Reputation: 235
I've noticed that in c/c++ a lot of Win32 API structs need to be told how big they are.
i.e someStruct.pbFormat = sizeof(SomeStruct)
Why is this the case? Is it just for legacy reasons? Also any idea what "pb" stands for too?
EDIT: oops, yeah I meant "cbFormat"
Upvotes: 8
Views: 505
Reputation: 41106
This is for backward compatibility when Windows API is extended.
Imagine the following declarations
struct WinData
{
long flags;
}
BOOL GetWinData(WinData * wd);
which you are calling like this:
WinData wd;
GetWinData(&wd);
A future OS version may extend this to
struct WinData
{
long flags;
long extraData;
}
However, if you have compiled against the "older" SDK, GetWinData
has no chance to figure out you don't know about extraData
. If it would fill it in regardless, it would overwrite data on the stack. BOOOM!
That's why, the "size known to the caller" is added to the structure, and new members are appended at the end. The GetWinData
implementation can inspect the size and decide "this poor guy doesn't know about all the new features yet".
Upvotes: 12
Reputation: 76510
Because Win32 API is a C API - not C++, so object orientated methods of extending the API are not available. With C++ API a new feature would use a structure that derives from the older one and call an interface that take the base structure, ensuring type safety.
C is a procedural language and is more limited in what you can do with structures.
Upvotes: 1
Reputation: 993105
This is so that the structure can be extended in future versions of the API, and Windows can then know (by the size the caller passed in) which fields should be looked at or not. It's basically a crude form of API versioning.
Usually those count bytes are prefixed with cb
, which stands for "count of bytes". For example, the STARTUPINFO
structure starts with:
typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
...
} STARTUPINFO, *LPSTARTUPINFO;
This was extended at some point with the STARTUPINFOEX
structure, which contains the same first part but a different size. Depending on the value of cb
, Windows will know whether or not to look at the new lpAttributeList
field.
Upvotes: 8
Reputation: 1012
The pb is an example of Hungarian Notation, basically a scheme for encoding a variable type into its name.
Upvotes: 1
Reputation: 76541
So that future versions can add extra fields and still be able to provide backwards binary compatibility:
// 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
}
Upvotes: 0