Cast to a struct?

J

Jack

Is it possible to cast a 4-byte data type (e.g. an unsigned int) to a
4-byte struct? Sometimes the HIWORD and LOWORD of a 4-byte value
contain information independent of each other. Is there a direct way
to perform this cast? If not, is there way in C++ to do it?

For example, I would like my function test() to work the way it is
coded below. It produces a compiler error though:

#include <pshpack2.h> // 16-bit padding

// My 4-byte struct
typedef struct _mystruct_t
{
unsigned short cx;
unsigned short cy;
} mystruct_t;

#include <poppack.h>

mystruct_t test()
{
unsigned int n = 0xffff0001;
return (mystruct_t)n;
}

int main()
{
mystruct_t s = test();
return 0;
}
 
I

Ian Collins

Jack said:
Is it possible to cast a 4-byte data type (e.g. an unsigned int) to a
4-byte struct? Sometimes the HIWORD and LOWORD of a 4-byte value
contain information independent of each other. Is there a direct way
to perform this cast? If not, is there way in C++ to do it?
Shouldn't that be C?

If you want to overlay types of the same size, use a union.
 
K

Keith Thompson

Jack said:
Is it possible to cast a 4-byte data type (e.g. an unsigned int) to a
4-byte struct? Sometimes the HIWORD and LOWORD of a 4-byte value
contain information independent of each other. Is there a direct way
to perform this cast?

No. Neither the source expression nor the target type of a cast is
allowed to be a struct (except that any expression can be cast to
void).
If not, is there way in C++ to do it?

How would we know that?
For example, I would like my function test() to work the way it is
coded below. It produces a compiler error though:

#include <pshpack2.h> // 16-bit padding

// My 4-byte struct
typedef struct _mystruct_t
{
unsigned short cx;
unsigned short cy;
} mystruct_t;

#include <poppack.h>

mystruct_t test()
{
unsigned int n = 0xffff0001;
return (mystruct_t)n;
}

int main()
{
mystruct_t s = test();
return 0;
}

I think you've misunderstood what a cast is for.

A cast specifies a type conversion. A conversion takes the *value* of
a source expression, and yields a value of another type (or the same
type); the result has some close relationship to the original value
(for example, it may be the same value in the case of a numeric
conversion). A conversion operates on values, not representations; it
doesn't just reinterpret the bits of the representation of the source.

For example, the cast expression (double)42 yields the value 42.0; the
int value 42 and the double value 42.0 have the same mathematical
value, but completely different representations.

(Pointer conversions typically work by reinterpreting bits, but only
because that makes sense in terms of the values.)

Looking at your code:

Avoid identifiers starting with '_'. Some of them are reserved to the
implementation in some or all contexts. It's much easier to avoid
such identifiers altogether than to remember the special cases in
which you can get away with using them.

Personally, I wouldn't use a typedef at all; I'd just declare the type
as "struct mystruct_t", and refer to it as "struct mystruct_t". But
if you prefer to use the typedef, it perfectly legal.

You're assuming, I think, that unsigned short is exactly 16 bits, and
unsigned int is exactly 32 bits. If the code isn't intended to be
portable, that may be acceptable; otherwise your code is likely to
break on systems where that isn't the case. (You also can't portably
assume that unsigned int is exactly twice as big as unsigned short;
I've worked on systems where it's the same size, and on others where
it's four times as big.)

What is the conversion supposd to do? I'm guessing you want to store
0xffff in one of the members and 0x0001 in the other, but which is
which? If you copy the value directly (using memcpy, or a union, or
pointer tricks), the results will vary depending on whether your
platform is big-endian or little-endian. You'll need to decide
exactly what you want to do before you can figure out the best way to
do it.

Finally, <pshpack2.h> and <poppack.h> are non-standard headers, and I
don't know what you mean by "16-bit padding".
 
M

MQ

I
If you want to overlay types of the same size, use a union.

Wouldn't that depend upon the implementation of the compiler/platform,
in terms of how it represents the data type. It sounds like the OP
wants to do something like:

struct C
{
short hiword;
short loword;
};
union A
{
int b
struct C c;
};

would this not possibly behave differently depending on whether it was
compiled on a little-endain or big-endian machine?
 
F

Flash Gordon

MQ said:
I

Wouldn't that depend upon the implementation of the compiler/platform,
in terms of how it represents the data type. It sounds like the OP
wants to do something like:

struct C
{
short hiword;
short loword;
};
union A
{
int b
struct C c;
};

would this not possibly behave differently depending on whether it was
compiled on a little-endain or big-endian machine?

Yes, you are correct. Even worse, the compiler might insert padding
between hiword and loword so even on a system where short is half the
size of int the struct could be longer than an int.

Depending on what the OP actually wants to achieve, either using a
pointer to unsigned char pointing at the int or using shifting and
masking would be better. With the shifting/masking you are best working
with unsigned int otherwise you can get unexpected results.
 
H

Herbert Rosenau

Is it possible to cast a 4-byte data type (e.g. an unsigned int) to a
4-byte struct?

No.

Sometimes the HIWORD and LOWORD of a 4-byte value
contain information independent of each other. Is there a direct way
to perform this cast? If not, is there way in C++ to do it?

You are leaving the lands of standard C. What you tries is higly
implementation specific and has nothing to do with standard C. Find a
group that is related to your implementation and ask there for a way
to get it - if it is possible.

At least you gets an application that is in no way compatible - maybe
not even between 2 different versions of the compiler you are using.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
 
S

SM Ryan

# Is it possible to cast a 4-byte data type (e.g. an unsigned int) to a
# 4-byte struct? Sometimes the HIWORD and LOWORD of a 4-byte value
# contain information independent of each other. Is there a direct way
# to perform this cast? If not, is there way in C++ to do it?
#
# For example, I would like my function test() to work the way it is
# coded below. It produces a compiler error though:
#
# #include <pshpack2.h> // 16-bit padding
#
# // My 4-byte struct
# typedef struct _mystruct_t
# {
# unsigned short cx;
# unsigned short cy;
# } mystruct_t;
#
# #include <poppack.h>
#
# mystruct_t test()
# {
# unsigned int n = 0xffff0001;
# return (mystruct_t)n;
# }

You can use memcpy
assert(sizeof n==sizeof(mystruct_t));
mystruct_t N;
memcpy(&N,&n,sizeof n);
return N;

# int main()
# {
# mystruct_t s = test();
# return 0;
# }
#
#
 

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

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top