a C++ question about union

J

JDT

NM_UPDOWN

With UDN_DELTAPOS notification handler, MS passes a pointer to NMHDR
which yo can cast to NM_UPDOWN*. With NMHDR (shown below) , you can use
"iDelta" to know the amount it spins while with NMHDR you can use "code"
to know the event type. What I don't understand is why the same storage
(the overlap of the last int and unsigned int) can provide two different
values by casting. Is it not union, is it? This is a C++ (or even a C)
question. If I underhand it, I may exploit the same tech for my own.
Your advise is appreciated. JD

typedef struct _NM_UPDOWN
{
NMHDR hdr;
int iPos;
int iDelta;
} NMUPDOWN, *LPNMUPDOWN;

typedef struct tagNMHDR
{
HWND hwndFrom;
UINT_PTR idFrom;
UINT code; // NM_ code
} NMHDR;
 
V

Victor Bazarov

JDT said:
NM_UPDOWN

With UDN_DELTAPOS notification handler, MS passes a pointer to NMHDR
which yo can cast to NM_UPDOWN*. With NMHDR (shown below) , you can
use "iDelta" to know the amount it spins while with NMHDR you can use
"code" to know the event type. What I don't understand is why the
same storage (the overlap of the last int and unsigned int) can
provide two different values by casting. Is it not union, is it? This is
a C++ (or even a C) question. If I underhand it, I may
exploit the same tech for my own. Your advise is appreciated. JD

typedef struct _NM_UPDOWN
{
NMHDR hdr;
int iPos;
int iDelta;
} NMUPDOWN, *LPNMUPDOWN;

typedef struct tagNMHDR
{
HWND hwndFrom;
UINT_PTR idFrom;
UINT code; // NM_ code
} NMHDR;

So much MS stuff here, my head hurts... Perhaps next time you will
rephrase to avoid using their abbreivations and all-capital-letters
names... It would be so nice...

Anyway, what you're asking about is akin to the fact that if I have
a "hierarchy" like this

struct A {
int a;
};

struct B {
A a;
double d;
};

, I could do the following:

#include <iostream>
void foo(A* pa) {
B* pb = (B*) pa;
std::cout << "The 'd' is " << pb->d << std::endl;
}

int main() {
B b = { { 42 }, 3.14159 };
foo(& b.a);
}

Well, yes, that's "allowed". The layout of any POD object is pretty
much preset, in the sense that 'd' follows 'a' in a 'B' and that the
address of 'a' in a 'B' is the same as the address of the 'B' itself.

V
 
I

Ian Collins

JDT said:
NM_UPDOWN

With UDN_DELTAPOS notification handler, MS passes a pointer to NMHDR
which yo can cast to NM_UPDOWN*. With NMHDR (shown below) , you can use
"iDelta" to know the amount it spins while with NMHDR you can use "code"
to know the event type. What I don't understand is why the same storage
(the overlap of the last int and unsigned int) can provide two different
values by casting. Is it not union, is it? This is a C++ (or even a C)
question. If I underhand it, I may exploit the same tech for my own.
Your advise is appreciated. JD
It's not a technique, it's a horrible kludge.
 
A

Andre Kostur

NM_UPDOWN

With UDN_DELTAPOS notification handler, MS passes a pointer to NMHDR
which yo can cast to NM_UPDOWN*. With NMHDR (shown below) , you can use
"iDelta" to know the amount it spins while with NMHDR you can use "code"
to know the event type. What I don't understand is why the same storage
(the overlap of the last int and unsigned int) can provide two different
values by casting. Is it not union, is it? This is a C++ (or even a C)
question. If I underhand it, I may exploit the same tech for my own.
Your advise is appreciated. JD

typedef struct _NM_UPDOWN
{
NMHDR hdr;
int iPos;
int iDelta;
} NMUPDOWN, *LPNMUPDOWN;

typedef struct tagNMHDR
{
HWND hwndFrom;
UINT_PTR idFrom;
UINT code; // NM_ code
} NMHDR;

This is more of a C question than C++, but here goes:


Note that the first member of _NM_UPDOWN is an NMHDR.

So what MS is doing behind the scenes is something like:


{
_NM_UPDOWN notification;

notification.hdr.code = NM_WhateverCode;

CallNotificationFunction(reinterpret_cast<NMHDR *>(&notification);
}


Basically it's relying on the fact that the first part of the NM_UPDOWN
struct actually is a NMHDR object. It's kinda trying to implement
inheritance in the C world.

So when MS is passing you a pointer to NMHDR, it's really passing you a
pointer to the hdr member of an NM_UPDOWN struct. Keep in mind that the
pointer to the first member of a struct is the same as a pointer to the
struct itself.
 
V

Victor Bazarov

Ian said:
It's not a technique, it's a horrible kludge.

[Mostly directed at the OP]

IOW, there are more reliable ways to do that in C++. However, in C,
since there is no inheritance, relying on certain relationship
between a pointer to a struct member and and the struct object itself
is not completely unheard of. Think "offsetof" macro.

And since we are in a C++ newsgroup, there is probably more merit in
stating what problem you're trying to solve, so that a solution or
two (or three) can be proposed, instead of showing some other solution
to some other problem in an attempt to see if it solves something else
you have not encountered yet...

V
 
I

Ian Collins

Victor said:
Ian said:
It's not a technique, it's a horrible kludge.


[Mostly directed at the OP]

IOW, there are more reliable ways to do that in C++. However, in C,
since there is no inheritance, relying on certain relationship
between a pointer to a struct member and and the struct object itself
is not completely unheard of. Think "offsetof" macro.
It's still a horrible kludge. If you want to do such things in C, use a
union of structures with the first member of each struct being the type
identifier.
 
V

Victor Bazarov

Ian said:
Victor said:
Ian said:
JDT wrote:

NM_UPDOWN

With UDN_DELTAPOS notification handler, MS passes a pointer to
NMHDR which yo can cast to NM_UPDOWN*. With NMHDR (shown below) ,
you can use "iDelta" to know the amount it spins while with NMHDR
you can use "code" to know the event type. What I don't
understand is why the same storage (the overlap of the last int
and unsigned int) can provide two different values by casting. Is
it not union, is it? This is a C++ (or even a C) question. If I
underhand it, I may exploit the same tech for my own. Your advise
is appreciated. JD


It's not a technique, it's a horrible kludge.


[Mostly directed at the OP]

IOW, there are more reliable ways to do that in C++. However, in C,
since there is no inheritance, relying on certain relationship
between a pointer to a struct member and and the struct object itself
is not completely unheard of. Think "offsetof" macro.
It's still a horrible kludge. If you want to do such things in C,
use a union of structures with the first member of each struct being
the type identifier.

I don't see how it's better, and that's probably why I don't understand
the "horrible" attribute you used in your charcterisation.

V
 
I

Ian Collins

Victor said:
Ian said:
Victor said:
Ian Collins wrote:

JDT wrote:

NM_UPDOWN

With UDN_DELTAPOS notification handler, MS passes a pointer to
NMHDR which yo can cast to NM_UPDOWN*. With NMHDR (shown below) ,
you can use "iDelta" to know the amount it spins while with NMHDR
you can use "code" to know the event type. What I don't
understand is why the same storage (the overlap of the last int
and unsigned int) can provide two different values by casting. Is
it not union, is it? This is a C++ (or even a C) question. If I
underhand it, I may exploit the same tech for my own. Your advise
is appreciated. JD

It's not a technique, it's a horrible kludge.

[Mostly directed at the OP]

IOW, there are more reliable ways to do that in C++. However, in C,
since there is no inheritance, relying on certain relationship
between a pointer to a struct member and and the struct object itself
is not completely unheard of. Think "offsetof" macro.

It's still a horrible kludge. If you want to do such things in C,
use a union of structures with the first member of each struct being
the type identifier.

I don't see how it's better, and that's probably why I don't understand
the "horrible" attribute you used in your charcterisation.
Posting pre-coffee....

I should have written If you want to do such things in C, use a union of
structures with the first member of each struct and the union being the
type identifier, thus:

struct A {
int type;
/* Other members */
};

struct B {
int type;
/* Other members */
};

typedef union {
int type;
struct A a;
struct B b;
} Event;

It is then clear to the reader what an Event is and which types of event
are supported.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top