Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Casting a void * into a 32-bit struct

Reply
Thread Tools

Casting a void * into a 32-bit struct

 
 
Luc Le Blanc
Guest
Posts: n/a
 
      11-11-2003
I have 2 APIs that store/recall a void *. Since all I need to store is a
32-bit struct, I pass the actual data (instead of a pointer to it) as a
void *:

typedef
{
UInt8 color;
UInt8 index;
UInt16 resID;
} GadgetData;

GadgetData data;

data.color = ...

FrmSetGadgetData( ..., ( void * ) *( UInt32 * ) &data );

Now, I would like to retrieve this void * returned by FrmGetGadgetData
back into a GadgetData struct:

GadgetData data = FrmGetGadgetData( ... );

but I can't find the proper way to cast a void * into my GadgetData
struct.


--
Luc Le Blanc

 
Reply With Quote
 
 
 
 
Jim
Guest
Posts: n/a
 
      11-11-2003
On Mon, 10 Nov 2003 21:26:36 -0500, Luc Le Blanc <(E-Mail Removed)>
wrote:

>I have 2 APIs that store/recall a void *. Since all I need to store is a
>32-bit struct, I pass the actual data (instead of a pointer to it) as a
>void *:
>
>typedef
>{
> UInt8 color;
> UInt8 index;
> UInt16 resID;
>} GadgetData;
>
>GadgetData data;
>
>data.color = ...
>
>FrmSetGadgetData( ..., ( void * ) *( UInt32 * ) &data );
>
>Now, I would like to retrieve this void * returned by FrmGetGadgetData
>back into a GadgetData struct:
>
>GadgetData data = FrmGetGadgetData( ... );
>
>but I can't find the proper way to cast a void * into my GadgetData
>struct.


data = *(GadgetData *)FrmGetGadgetData(...);

But I think you're making a (totally OT) mistake in the Set part
anyway.

 
Reply With Quote
 
 
 
 
those who know me have no need of my name
Guest
Posts: n/a
 
      11-11-2003
in comp.lang.c i read:

>I have 2 APIs that store/recall a void *. Since all I need to store is a
>32-bit struct, I pass the actual data (instead of a pointer to it) as a
>void *:


serious mistake -- your code will have undefined behavior. use a union
instead.

--
a signature
 
Reply With Quote
 
Scott Fluhrer
Guest
Posts: n/a
 
      11-11-2003

"Jim" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On Mon, 10 Nov 2003 21:26:36 -0500, Luc Le Blanc <(E-Mail Removed)>
> wrote:
>
> >I have 2 APIs that store/recall a void *. Since all I need to store is a
> >32-bit struct, I pass the actual data (instead of a pointer to it) as a
> >void *:
> >
> >typedef
> >{
> > UInt8 color;
> > UInt8 index;
> > UInt16 resID;
> >} GadgetData;
> >
> >GadgetData data;
> >
> >data.color = ...
> >
> >FrmSetGadgetData( ..., ( void * ) *( UInt32 * ) &data );

This doesn't do what the OP thinks it does. This doesn't store the actual
contents of data as a 32 bit pointer, this stores a pointer to the data
structure.

> >
> >Now, I would like to retrieve this void * returned by FrmGetGadgetData
> >back into a GadgetData struct:
> >
> >GadgetData data = FrmGetGadgetData( ... );
> >
> >but I can't find the proper way to cast a void * into my GadgetData
> >struct.

>
> data = *(GadgetData *)FrmGetGadgetData(...);
>
> But I think you're making a (totally OT) mistake in the Set part
> anyway.

Based on the OP's description (and not his code), that's not what he wants
to do. He doesn't want to dereference the pointer FrmGetGadgetData returns.
Instead, he wants to interpret the bit
pattern of that pointer as a GadgetData structure.

About the best he can do (and either involves Undefined Behavior, however,
any
method of doing what he wants involves Undefined Behavior):

void *temp = FrmGetGadgetData(...);
GadgetData data = *(GadgetData*)&temp;

or

GadgetData data;
union {
void *pointer;
GadgetData data;
} x;
x.pointer = FrmGetGadgetData(...);
data = x.data;

I don't recommend either -- instead, I suggest he rethink the idea of saving
the 32 bits as a "pointer" value.

--
poncho



 
Reply With Quote
 
Christian Bau
Guest
Posts: n/a
 
      11-11-2003
In article <(E-Mail Removed)>, Luc Le Blanc <(E-Mail Removed)>
wrote:

> I have 2 APIs that store/recall a void *. Since all I need to store is a
> 32-bit struct, I pass the actual data (instead of a pointer to it) as a
> void *:
>
> typedef
> {
> UInt8 color;
> UInt8 index;
> UInt16 resID;
> } GadgetData;
>
> GadgetData data;
>
> data.color = ...
>
> FrmSetGadgetData( ..., ( void * ) *( UInt32 * ) &data );
>
> Now, I would like to retrieve this void * returned by FrmGetGadgetData
> back into a GadgetData struct:
>
> GadgetData data = FrmGetGadgetData( ... );
>
> but I can't find the proper way to cast a void * into my GadgetData
> struct.


The fact that you have to ask how to do this should be a strong hint
that you shouldn't do it.

Do the decent thing: void* p = malloc (sizeof GadgetData); memcpy (p,
&data); etc.
 
Reply With Quote
 
Anupam
Guest
Posts: n/a
 
      11-11-2003
"Scott Fluhrer" <(E-Mail Removed)> wrote in message news:<NS_rb.7026$(E-Mail Removed) nk.net>...
> "Jim" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
> > On Mon, 10 Nov 2003 21:26:36 -0500, Luc Le Blanc <(E-Mail Removed)>
> > wrote:
> >
> > >I have 2 APIs that store/recall a void *. Since all I need to store is a
> > >32-bit struct, I pass the actual data (instead of a pointer to it) as a
> > >void *:
> > >
> > >typedef
> > >{
> > > UInt8 color;
> > > UInt8 index;
> > > UInt16 resID;
> > >} GadgetData;
> > >
> > >GadgetData data;
> > >
> > >data.color = ...
> > >
> > >FrmSetGadgetData( ..., ( void * ) *( UInt32 * ) &data );

> This doesn't do what the OP thinks it does. This doesn't store the actual
> contents of data as a 32 bit pointer, this stores a pointer to the data
> structure.


I don't agree with you here.
Let's dissect : ( void * ) *( UInt32 * ) &data
It says to the compiler:
[ Consider only ( UInt32 * ) &data ]
Hey just assume that &data which used to point to a GadgetData
object in memory now points to an UInt32
Now consider :
( void * ) * .....
This says that take the object at this address ( now the compiler
thinks that since this address points to an UInt32 object) ... which
is a 32 bit object and forcibly say that this is a void * and pass it
to the function... finally the actual data bytes are being sent as a
32 bit pointer.


>
> > >
> > >Now, I would like to retrieve this void * returned by FrmGetGadgetData
> > >back into a GadgetData struct:
> > >
> > >GadgetData data = FrmGetGadgetData( ... );
> > >
> > >but I can't find the proper way to cast a void * into my GadgetData
> > >struct.

> >
> > data = *(GadgetData *)FrmGetGadgetData(...);
> >
> > But I think you're making a (totally OT) mistake in the Set part
> > anyway.

> Based on the OP's description (and not his code), that's not what he wants
> to do. He doesn't want to dereference the pointer FrmGetGadgetData returns.
> Instead, he wants to interpret the bit
> pattern of that pointer as a GadgetData structure.
>
> About the best he can do (and either involves Undefined Behavior, however,
> any
> method of doing what he wants involves Undefined Behavior):
>
> void *temp = FrmGetGadgetData(...);
> GadgetData data = *(GadgetData*)&temp;


Yup agreed.

Im guessing that the OP would have tried :
data = (GadgetData)(FrmGetGadgetData( ... ));
This gave a "incompatible type conversion" error . This is because
the C compiler thinks that this sort of a transformation need never be
done on the semantics of the identifier of an object.
>
> or
>
> GadgetData data;
> union {
> void *pointer;
> GadgetData data;
> } x;
> x.pointer = FrmGetGadgetData(...);
> data = x.data;
>
> I don't recommend either -- instead, I suggest he rethink the idea of saving
> the 32 bits as a "pointer" value.


Ok now here's the biggest catch ... as to why I think this is such a
*bad* idea. It's simply that this just may not work at all. Check out
the fact that the sum of the fields of a struct may not equal the
sizeof the struct at all. So your basic assumption that this is a 32
bit struct may not always be true. As we go along theres a LOT of UB
out here... but the start itself is one. Instead I would suggest that
the OP make his own API's .. they'd be worth the effort.
 
Reply With Quote
 
Chris Torek
Guest
Posts: n/a
 
      11-11-2003
In article <(E-Mail Removed) >
Anupam <(E-Mail Removed)> writes:
> I don't agree with you here.
>Let's dissect : ( void * ) *( UInt32 * ) &data
>It says to the compiler:
> [ Consider only ( UInt32 * ) &data ]
> Hey just assume that &data which used to point to a GadgetData
>object in memory now points to an UInt32


Actually, this does not tell a compiler to "assume", but rather to
*convert*. That is, if &data has type "pointer to GadgetData" (and
some valid value of that type), the compiler must now convert that
value to a new value, of type "pointer to UInt32". There is no
requirement that the new value be useful in any way, in this
particular case. Only "void *" (and by extension "char *") have
constraints strong enough to enforce "usefulness" of such conversions.

(On machines with multiple pointer formats, the computer must often
execute at least one CPU instruction in order to perform the
conversions produced by pointer casts. On computers with only
one pointer format, the conversion takes no instructions, but
is still a conversion.)

> Now consider :
> ( void * ) * .....
> This says that take the object at this address ( now the compiler
>thinks that since this address points to an UInt32 object) ...


More precisely, the compiler must follow the pointer value -- or
produce code to do this at runtime -- produced by the conversion
you requested earlier. For this operation to have a useful,
well-defined result, that pointer must in fact point to a valid
object of type "UInt32" (whatever that is -- presumably the same
as C99's uint32_t, though).

>which is a 32 bit object


(assuming the pointer is valid and the access produces a useful
32-bit object, yes...)

>and forcibly say that this is a void *


Once again, a cast does not mean "pretend it is" or even "it IS",
but rather "please convert it to". Conversions from integer to
pointer are implementation-defined:

[C99 draft, section 6.2.2.3]
An integer may be converted to any pointer type. The result
is implementation-defined, might not be properly aligned, and
might not point to an entity of the referenced type.

but are meant to do the "obvious thing" to anyone who is experienced
with the machine's internal representations. (On some machines,
reasonable people might even reasonably disagree as to what the
"obvious thing" should be, so even this is a little iffy.)

>Ok now here's the biggest catch ... as to why I think this is such a
>*bad* idea. It's simply that this just may not work at all. Check out
>the fact that the sum of the fields of a struct may not equal the
>sizeof the struct at all. So your basic assumption that this is a 32
>bit struct may not always be true. As we go along theres a LOT of UB
>out here... but the start itself is one.


Indeed. Additional possibilities include:

- the struct is 32 bits but is not properly aligned for access
as a "UInt32"
- the struct is 32 bits but "void *" is not

One case of the latter is rapidly becoming common today, with 64-bit
CPUs. Of course, 64 value are likely to be able to hold 32 value
bits without losing any bits, but the "thin ice" aspect of the
whole approach should be obvious by now.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://67.40.109.61/torek/index.html (for the moment)
Reading email is like searching for food in the garbage, thanks to spammers.
 
Reply With Quote
 
Scott Fluhrer
Guest
Posts: n/a
 
      11-11-2003

"Anupam" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) om...
> "Scott Fluhrer" <(E-Mail Removed)> wrote in message

news:<NS_rb.7026$(E-Mail Removed) nk.net>...
> > "Jim" <(E-Mail Removed)> wrote in message
> > news:(E-Mail Removed)...
> > > On Mon, 10 Nov 2003 21:26:36 -0500, Luc Le Blanc <(E-Mail Removed)>
> > > wrote:
> > >
> > > >I have 2 APIs that store/recall a void *. Since all I need to store

is a
> > > >32-bit struct, I pass the actual data (instead of a pointer to it) as

a
> > > >void *:
> > > >
> > > >typedef
> > > >{
> > > > UInt8 color;
> > > > UInt8 index;
> > > > UInt16 resID;
> > > >} GadgetData;
> > > >
> > > >GadgetData data;
> > > >
> > > >data.color = ...
> > > >
> > > >FrmSetGadgetData( ..., ( void * ) *( UInt32 * ) &data );

> > This doesn't do what the OP thinks it does. This doesn't store the

actual
> > contents of data as a 32 bit pointer, this stores a pointer to the data
> > structure.

>
> I don't agree with you here.


Oops, you are right -- I misread this.

--
poncho


 
Reply With Quote
 
Anupam
Guest
Posts: n/a
 
      11-12-2003
Chris Torek <(E-Mail Removed)> wrote in message news:<boqrnk$43k$(E-Mail Removed)>...
> In article <(E-Mail Removed) >
> Anupam <(E-Mail Removed)> writes:
> > I don't agree with you here.
> >Let's dissect : ( void * ) *( UInt32 * ) &data
> >It says to the compiler:
> > [ Consider only ( UInt32 * ) &data ]
> > Hey just assume that &data which used to point to a GadgetData
> >object in memory now points to an UInt32

>
> Actually, this does not tell a compiler to "assume", but rather to
> *convert*.


Absolutely, I slipped up in the phraseology there.

> (On machines with multiple pointer formats, the computer must often
> execute at least one CPU instruction in order to perform the
> conversions produced by pointer casts. On computers with only
> one pointer format, the conversion takes no instructions, but
> is still a conversion.)


Well, well this is a nice fact ... my language showed my inner sort
of feeling that pointers remain pointers ... no real manipulation is
done ... shows the dangers of the one architecture mindset.

[snip]

I absolutely agree with all the comments there.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
What is the difference between void proba(); and void proba(void); ??? PencoOdStip@gmail.com C++ 1 05-23-2007 07:12 PM
what is the difference, void func(void) and void fucn() noblesantosh@yahoo.com C Programming 5 07-22-2005 04:38 PM
"void Method()" vs "void Method(void)" Ollej Reemt C++ 7 04-22-2005 03:47 AM
Casting const void * into void * Enrico `Trippo' Porreca C Programming 14 06-04-2004 03:30 PM
`void **' revisited: void *pop(void **root) Stig Brautaset C Programming 15 10-28-2003 09:03 AM



Advertisments