Reputation: 567
I can't figure out what this macro means:
#define DECLARE_HANDLE(n) typedef struct n##__{int i;}*n
DECLARE_HANDLE(HWND);
I have learned from the C program that:
"##" means connect the parameter.
so the macro equals:
typedef struct HWND__{int i;}*HWND
Is this right?
If it is right, what is the meaning of that sentence?
==================
Code from a game Bombermaaan (for Windows and Linux),
link http://sourceforge.net/p/bombermaaan/code/HEAD/tree/trunk/src/Bombermaaan/winreplace.h,
line No 90.
Upvotes: 9
Views: 2513
Reputation: 14408
Your assumption is correct.
You can check this with the following simple test code.
DECLARE_HANDLE(HWND);
struct HWND__ s;
HWND p = (HWND) malloc(sizeof(struct HWND__));
s.i = 20;
p->i = 100;
cout << "i valueis " << s.i<<" and " << p->i <<endl;
Upvotes: 6
Reputation: 13551
Exactly.
This is used to declare an opaque pointer to a structure that is unknown to you.
I don't know why they didn't simply declare it as a
typedef void* HWND;
Probably for alignment issues, since structures can be aligned but not basic types.
As mentioned above, declaring the type as a structure permits some compile-time type checking.
Clever!
Upvotes: 2
Reputation: 129374
The main purpose of this construct is to prevent the misuse of handles. If all handles are simply void *
or int
or long long
or some other basic type, there is nothing to prevent you from using one instead of another. A pointer to a struct HWND__
and pointer to struct HBITMAP__
isn't the same thing, so if you have a the following code:
HWND hwnd;
HBITMAP hbmp;
hbmp = GetBitmap(...);
hwnd = hbmp; // gives compiler error.
It's a fairly classic technique to ensure that you get unique types for something that the API supplier don't want to provide the true declaration for. Although I'm not entirely sure why they even need a proper struct declaration, you could probably get away with:
#define DECLARE_HANDLE(n) struct n ## __; struct n ## __ *n;
That will also ensure that any dereferece HWND won't be possible, since the compiler will object to "use of incomplete type".
Upvotes: 11
Reputation: 4760
DECLARE_HANDLE(HWND);
indeed expands to
typedef struct HWND__{int i;}*HWND;
Now, you're asking what it means? Just split the typedef into two steps:
struct HWND__
{
int i;
};
typedef HWND__* HWND; // C++ only; for both C++ and C: typedef struct HWND__* HWND;
Thus, it defines a struct HWND__
containing an int
(named i
) and declares a type alias HWND
as pointer to HWND__
.
Upvotes: 1
Reputation: 10126
It defines a HWND
as a pointer to struct HWND__
that contains int i
.
So, now you can use in the code the type HWND
.
Upvotes: 0