About unions

J

john

Hello,
how do I merge the following two structures using an union?

struct {
unsigned char A;
unsigned char R;
unsigned char G;
unsigned char B;
} Color;

struct {
unsigned long ARGB;
} Color;

I want the following two blocks of code to be equivalent (in data memory):

Color.A=0x10; Color.R=0x20; Color.G=0x30; Color.B=0x40;
and
Color.ARGB=0x10203040;

Thanks!
John
 
M

Martin Johansen

Depending on the endianess of you system, this will work

union{
struct {
unsigned char A;
unsigned char R;
unsigned char G;
unsigned char B;
} Color;

struct {
unsigned long ARGB;
} ColorC;
}ColorU;

With an opposite endianess, reverse the bytes in struct 1 (Color).
 
M

Marc Boyer

how do I merge the following two structures using an union?

struct {
unsigned char A;
unsigned char R;
unsigned char G;
unsigned char B;
} Color;

struct {
unsigned long ARGB;
} Color;

I want the following two blocks of code to be equivalent (in data memory):

Color.A=0x10; Color.R=0x20; Color.G=0x30; Color.B=0x40;
and
Color.ARGB=0x10203040;

You can not in a portable way, because (at least):
a) they could be padding between the fields A,R,G,B in the
first struct
b) you have no garanties that sizeof(unsigned long)==4
c) char orders depends on endianness

For a given compiler, it could works with
union {
struct {
unsigned char A;
unsigned char R;
unsigned char G;
unsigned char B;
} chars;
unsigned long ARGB;
} Color;

Color c;
c.chars.A= 0x10;

You can protect yourself from a) and b) with
testing that sizeof(Color)==4. Detecting endianness
can also be checked.
But the easiest portable way is IMHO to have
struct {
unsigned char components[4];
} Color;
and to write the functions
setColor(Color* c, unsigned long);
setComponent(Color* c, unsigned char value, unsigned int component);
setComponentA(Color* c, unsigned char value);
setComponentB(Color* c, unsigned char value);
setComponentC(Color* c, unsigned char value);
setComponentD(Color* c, unsigned char value);

Marc Boyer
 
K

Kenny McCormack

Hello,
how do I merge the following two structures using an union?

struct {
unsigned char A;
unsigned char R;
unsigned char G;
unsigned char B;
} Color;

struct {
unsigned long ARGB;
} Color;

I want the following two blocks of code to be equivalent (in data memory):

Color.A=0x10; Color.R=0x20; Color.G=0x30; Color.B=0x40;
and
Color.ARGB=0x10203040;

Thanks!
John

Not portable. Can't discuss it here. Blah, blah, blah.
 
A

Andrey Tarasevich

how do I merge the following two structures using an union?

struct {
unsigned char A;
unsigned char R;
unsigned char G;
unsigned char B;
} Color;

struct {
unsigned long ARGB;
} Color;

I want the following two blocks of code to be equivalent (in data memory):

Color.A=0x10; Color.R=0x20; Color.G=0x30; Color.B=0x40;
and
Color.ARGB=0x10203040;
...

This cannot be done in general case. Read your compiler/platform documentation
to find out whether it is possible in your particular case.
 
M

Mark McIntyre

Hello,
how do I merge the following two structures using an union?

union
{
struct
{
unsigned char A;
unsigned char R;
unsigned char G;
unsigned char B;
}ColorRGB;
unsigned long ColorARGB;
// or use your other struct here.
}

As for using it tho...

This is not only platform specific, but also not allowed by the C
Standard. You're assuming

- sizeof unsigned long == 4 * sizeof unsigned char,
- byte ordering in a long is little-endian,
- you can safely read a union by a type other than the one you last
wrote to it by

None of these is guaranteed, and the last is expressly forbidden.
 
T

Tim Rentsch

Mark McIntyre said:
union
{
struct
{
unsigned char A;
unsigned char R;
unsigned char G;
unsigned char B;
}ColorRGB;
unsigned long ColorARGB;
// or use your other struct here.
}

As for using it tho...

This is not only platform specific, but also not allowed by the C
Standard. You're assuming

- sizeof unsigned long == 4 * sizeof unsigned char,
- byte ordering in a long is little-endian,
- you can safely read a union by a type other than the one you last
wrote to it by

None of these is guaranteed, and the last is expressly forbidden.

Accessing a union member other than the last one stored into is
not expressly forbidden. There are the provisions about the last
stored value for effective type, but those don't enter into
consideration for objects with declared type (ie, any regular
variable rather than storage that has been malloc()'ed).

Annex J lists "the value of a union member other than the last
one stored into" as unspecified behavior, not undefined behavior.


Also, take a look at:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_283.htm


Note the TC at the bottom:

Technical Corrigendum

Attach a new footnote 78a to the words "named member" in 6.5.2.3#3:

78a If the member used to access the contents of a union
object is not the same as the member last used to store a
value in the object, the appropriate part of the object
representation of the value is reinterpreted as an object
representation in the new type as described in 6.2.6 (a
process sometimes called "type punning"). This might be a
trap representation.
 
M

Mark McIntyre

Accessing a union member other than the last one stored into is
not expressly forbidden.

Agreed, its not a constraint violation but its implementation defined
and unspecified behaviour, so you cannot rely on it working.
Note the TC at the bottom:

Technical Corrigendum

Attach a new footnote 78a to the words "named member" in 6.5.2.3#3:

ok, but this essentially makes the same point. The value cannot be
relied on to be valid
 
M

Mark B

Mark McIntyre said:
Agreed, its not a constraint violation but its implementation defined
and unspecified behaviour, so you cannot rely on it working.

Do you rely on printf() working? :)
ok, but this essentially makes the same point. The value cannot be
relied on to be valid

.... unless your implementation guarantees it (are there any that don't?)
 
M

Mark McIntyre

On Wed, 09 Nov 2005 21:30:02 GMT, in comp.lang.c , "Mark B"

Of accessing a union member by a different type to that last written.
... unless your implementation guarantees it (are there any that don't?)

Irrelevant - since its not required to, any practical example is
worthless.

Plus... name one whose documentation specifies that this works. As
opposed to one where practical examination says it works.
 
T

Tim Rentsch

Mark McIntyre said:
Agreed, its not a constraint violation but its implementation defined
and unspecified behaviour, so you cannot rely on it working.

For sure, it's not portable. But at the very least you can rely on
unspecified behavior not to blow up your computer or make demons
fly out of your nose; I think a lot of people would take comfort
in that, especially compared to the alternative. Unspecified
behavior doesn't automatically produce chaos; most programs have
lots of unspecified behavior in them.

ok, but this essentially makes the same point. The value cannot be
relied on to be valid

The wording in the new footnote makes it sound like reading a union
member other than the one last stored into will be (when the TC
takes effect) implementation defined behavior.

Implementation defined behavior provides a very strong guarantee.
Not only is it guaranteed to do *something*, but the implementation
must document what it has to do. This guarantee means that relying
on implementation defined behavior is perfectly reasonable on those
platforms that define the behavior as expected/desired. Obviously
that's not as strong a guarantee as platform independent behavior,
but in plenty of cases it's all that's needed.
 
T

Tim Rentsch

Mark McIntyre said:
On Wed, 09 Nov 2005 21:30:02 GMT, in comp.lang.c , "Mark B"

Of accessing a union member by a different type to that last written.


Irrelevant - since its not required to, any practical example is
worthless.

Plus... name one whose documentation specifies that this works. As
opposed to one where practical examination says it works.

The intention of the TC seems to be that what value results
can be deduced from what the implementation says about the
representation of types, which implementations are required
to do. I think most implementations provide that information
in one form or another.

(For those who missed it here is the text of that TC again:

Technical Corrigendum

Attach a new footnote 78a to the words "named member" in 6.5.2.3#3:

78a If the member used to access the contents of a union
object is not the same as the member last used to store a
value in the object, the appropriate part of the object
representation of the value is reinterpreted as an object
representation in the new type as described in 6.2.6 (a
process sometimes called "type punning"). This might be a
trap representation.

..)
 
M

Mark McIntyre

For sure, it's not portable. But at the very least you can rely on
unspecified behavior not to blow up your computer or make demons
fly out of your nose;

Terrific. So instead of crashing, your computer will stealthily
generate bogus data...
I think a lot of people would take comfort in that,

not in banking...
 
P

pete

Mark said:
Terrific. So instead of crashing, your computer will stealthily
generate bogus data...


not in banking...

I think the original main intended purpose of the union
were primarily to save space,
back in a time when space was more expensive than it usually is today.

I don't think it was ever intended to write one type
and read the object as another type.
 
M

Mark McIntyre

I think the original main intended purpose of the union
were primarily to save space,
back in a time when space was more expensive than it usually is today.

I don't think it was ever intended to write one type
and read the object as another type.

Could be. On the other hand, if you';ve ever used the old Excel
toolkit, you'll be familar with a marvellous example of the latter.
 

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
474,171
Messages
2,570,935
Members
47,472
Latest member
KarissaBor

Latest Threads

Top