Why is everything in the Windows API typedef'd?

In particular, why in many cases does the same typedef exist with several different names and why typedef pointer types (obscuring the logic from time to time)?

For instance:

typedef const WCHAR *LPCWSTR, *PCWSTR;

What is the meaning of this?

+6
source share
3 answers

The reason for having both PCWSTR and LPCWSTR is that in ancient times there was a difference. LPCWSTR was const WCHAR FAR *.

+7
source

In fact, several different things are happening here:

  • First Near / Far pointers: back in Win16 days you had near and far end pointers; almost pointers were basically just 16-bit offsets, so they could only refer to objects within the 64k default application data pointer (DS or data segment register), but they were small and fast; whereas the larger “far pointer” or long pointer consisted of a segment and an offset, so it could refer to something within 1 M of the address space. When 386 arrived, this whole segment: the offset business, finally left, and all the pointers were just 32-bit addresses into flat 32-bit address spaces. And that's why there are versions of P ... and LP ....

  • Why bother with typedefs in the first place? It’s just convenience or shortening: entering “LPSTR” is more convenient than “const char far *”. But it also becomes a recognizable idiom: you see LPSTR and you know right away that this is how Windows deals with strings in its API.

  • An abstraction also occurs here: Windows usually defines its own versions of types and uses them instead of versions C. Thus, the Windows API uses DWORD instead of int or VOID instead of void. This was necessary to connect some holes in C at that time - there was no bool, so the introduction of BOOL did not allow different APIs to use different types to represent logical values ​​(for example, char vs int). It also made the Windows API independent of the underlying C implementation to some extent: C does not require int to be a specific size: it could be 16 bits or 32 bits depending on the compiler. But for the OS API, it’s important to pinpoint these things. Therefore, instead of using int or long, Windows instead uses INT and LONG, which it then determines as necessary, and typedefs for any base type C does the actual job.

  • Finally, some of these typedefs actually hint at specific uses, with the exception of type information. BOOL and INT are typedef'd as int, but it is clear that the API parameter specified as BOOL will be used in the sense of TRUE / FALSE, and not as an integer value. (Remember that this precedes the “bool” type.) Similarly, BYTE — unsigned char — assumes that the parameter will actually be used as an 8-bit numeric value, and not as an alphanumeric character or character. And LPSTR indicates that the value is expected to be a zero-terminated string, and not just point to arbitrary char values. BSTR and LPWSTR have the same basic typedef - they are both WCHAR *, but BSTR have a length prefix and therefore must be selected using the SysAllocString API, and a separate typedef here helps to support two separate requirements in the code and the API document: if you see An API that takes BSTR as a parameter, then you know that you cannot just pass a wide string, even if the base type is the same, there are additional requirements for this parameter.

+18
source

I believe that one of the main goals of this project is to enable functions to perform functions of documenting their goals and expected data formats.

+4
source

Source: https://habr.com/ru/post/906172/


All Articles