Real Life Unions

K

Keith Thompson

CBFalconer said:
Richard said:
CBFalconer said:
Richard Heathfield wrote:

Counter-example:

union U { double d; unsigned char ir[sizeof(double)]; };
union U u;
size_t i;
u.d = 3.14159;
for(i = 0; i < sizeof(double); i++)
{
printf("%02X", u.ir);
}
putchar('\n');

But, strictly speaking, that's illegal, because you are reading
from a variant other than that last stored.


No, it isn't illegal. See 3.3.2.3. "With one exception, if a
member of a union object is accessed after a value has been
stored in a different member of the object, the behavior is
implementation-defined." Since when did we translate
"implementation-defined" as "illegal"?
After all, printf("%d\n", INT_MAX); is implementation-defined...


It is to me. I don't want the action of my software to be
dependant on the whims or profit motives of a William Gates.


Um, what is what to you? Are you saying that

printf("%d\n", INT_MAX);

is "illegal"? There might be a number of reasons to avoid writing
code whose behavior depends on the value of INT_MAX, but it's hardly
illegal.

[...]
 
K

Keith Thompson

Richard Heathfield said:
Chris Dollin said: [...]
I think you should present this with the "furniture",
/as an example of best practice/ on CLC.

And since you asked so nicely, Chris, I'm very glad to oblige:

#include <stdio.h>

union U { double d; unsigned char ir[sizeof(double)]; };

int main(void)
{
union U u;
size_t i;
u.d = 3.14159;
puts("The obj rep of (double)3.14159 on this system is:");

for(i = 0; i < sizeof(double); i++)
{
printf("%02X", u.ir);
}
putchar('\n');

return 0;
}


On my system, the above program produced the following output:

The obj rep of (double)3.14159 on this system is:
6E861BF0F9210940


Mine too (though on another system I got 400921F9F01B866E).

To be painfully pedantic, I'll point out that your program implicitly
assumes CHAR_BIT==8 (it prints two hex digits per byte). In most
real-world applications that's a perfectly reasonable assumption, but
here's a version that should work properly even on more exotic
systems:

#include <stdio.h>
#include <limits.h>

union U { double d; unsigned char ir[sizeof(double)]; };

int main(void)
{
union U u;
size_t i;

const int nybbles_per_byte = CHAR_BIT / 4 + (CHAR_BIT % 4 != 0);
/* Yeah, there's probably a cleaner way to do that. */

u.d = 3.14159;
puts("The obj rep of (double)3.14159 on this system is:");

for (i = 0; i < sizeof(double); i++) {
if (i != 0) putchar(':');
printf("%0*X", nybbles_per_byte, u.ir);
}
putchar('\n');

return 0;
}

Note that I've inserted :' characters between bytes in the output,
resulting in:

6E:86:1B:F0:F9:21:09:40

I'm not able to test it on a CHAR_BIT>8 system, but it does work as
expected if I manually change the value of nybbles_per_byte.
 
Y

Yevgen Muntyan

Keith said:
CBFalconer said:
Richard said:
CBFalconer said:
Richard Heathfield wrote:
Counter-example:

union U { double d; unsigned char ir[sizeof(double)]; };
union U u;
size_t i;
u.d = 3.14159;
for(i = 0; i < sizeof(double); i++)
{
printf("%02X", u.ir);
}
putchar('\n');
But, strictly speaking, that's illegal, because you are reading
from a variant other than that last stored.
No, it isn't illegal. See 3.3.2.3. "With one exception, if a
member of a union object is accessed after a value has been
stored in a different member of the object, the behavior is
implementation-defined." Since when did we translate
"implementation-defined" as "illegal"?
After all, printf("%d\n", INT_MAX); is implementation-defined...

It is to me. I don't want the action of my software to be
dependant on the whims or profit motives of a William Gates.


Um, what is what to you? Are you saying that

printf("%d\n", INT_MAX);

is "illegal"? There might be a number of reasons to avoid writing
code whose behavior depends on the value of INT_MAX, but it's hardly
illegal.


If implementation says that after "u.d = 3.14159;" u.ir will get you
a zero-filled array, then this code gets a serious problem. Of course,
"illegal" is the word you are arguing to, not what Chuck says about
evil implementation which breaks code...

Yevgen
 
C

CBFalconer

Keith said:
CBFalconer said:
Richard said:
CBFalconer said:
Richard Heathfield wrote:

Counter-example:

union U { double d; unsigned char ir[sizeof(double)]; };
union U u;
size_t i;
u.d = 3.14159;
for(i = 0; i < sizeof(double); i++)
{
printf("%02X", u.ir);
}
putchar('\n');

But, strictly speaking, that's illegal, because you are reading
from a variant other than that last stored.

No, it isn't illegal. See 3.3.2.3. "With one exception, if a
member of a union object is accessed after a value has been
stored in a different member of the object, the behavior is
implementation-defined." Since when did we translate
"implementation-defined" as "illegal"?
After all, printf("%d\n", INT_MAX); is implementation-defined...


It is to me. I don't want the action of my software to be
dependant on the whims or profit motives of a William Gates.


Um, what is what to you? Are you saying that

printf("%d\n", INT_MAX);

is "illegal"? There might be a number of reasons to avoid writing
code whose behavior depends on the value of INT_MAX, but it's
hardly illegal.


No, I was referring to the 'counter example', which is
implementation defined in the extraction from the union. I thought
that was obvious.
 
K

Keith Thompson

Yevgen Muntyan said:
Keith said:
CBFalconer said:
Richard Heathfield wrote: [...]
Since when did we translate
"implementation-defined" as "illegal"?
After all, printf("%d\n", INT_MAX); is implementation-defined...
It is to me. I don't want the action of my software to be
dependant on the whims or profit motives of a William Gates.
Um, what is what to you? Are you saying that
printf("%d\n", INT_MAX);
is "illegal"? There might be a number of reasons to avoid writing
code whose behavior depends on the value of INT_MAX, but it's hardly
illegal.

If implementation says that after "u.d = 3.14159;" u.ir will get you
a zero-filled array, then this code gets a serious problem. Of course,
"illegal" is the word you are arguing to, not what Chuck says about
evil implementation which breaks code...

It's not inconceivable that the representation of 3.14159 happens to
be all-bits-zero, but I fail to see what that has to do with my
question. I was *only* asking Chuck to clarify his remark about
printf("%d\n", INT_MAX);

This is, of course, a public forum, and I don't mean to imply that
only Chuck is allowed to answer a question that I addressed to him,
but you just didn't address what I said.
 
Y

Yevgen Muntyan

Keith said:
Yevgen Muntyan said:
Keith said:
Richard Heathfield wrote: [...]
Since when did we translate
"implementation-defined" as "illegal"?
After all, printf("%d\n", INT_MAX); is implementation-defined...
It is to me. I don't want the action of my software to be
dependant on the whims or profit motives of a William Gates.
Um, what is what to you? Are you saying that
printf("%d\n", INT_MAX);
is "illegal"? There might be a number of reasons to avoid writing
code whose behavior depends on the value of INT_MAX, but it's hardly
illegal.
If implementation says that after "u.d = 3.14159;" u.ir will get you
a zero-filled array, then this code gets a serious problem. Of course,
"illegal" is the word you are arguing to, not what Chuck says about
evil implementation which breaks code...

It's not inconceivable that the representation of 3.14159 happens to
be all-bits-zero,

I didn't say that. I have C89 words quoted by Richard in mind:

With one exception, if a member of a union object is accessed after a
value has been stored in a different member of the object, the behavior
is implementation-defined.

It looks reasonable to assume that "get an object which consists
of the same bits" is not the only possible (DS9000?) behavior.
but I fail to see what that has to do with my
question. I was *only* asking Chuck to clarify his remark about
printf("%d\n", INT_MAX);

Well, you replied not to the post where he said that, but to
the post where he said he doesn't want "to be dependant on the
whims or profit motives of a William Gates", i.e. it seemed clear
he didn't want to insist on "illegal", but he still didn't like
"implementation-defined" part... I might have misunderstood
it.

Yevgen
 
K

Kenneth Brody

Yevgen Muntyan wrote:
[...]
X events example). It's also true that what your example is
completely off-topic here, even more off-topic than usual, since you
are saving/loading structure content and that's non-portable, breaks
across implementations, may break even on the same implementation, etc.

Just because the data file generated by a particular program is
not portable does not mean that the program itself isn't. (After
all, one could argue that a simple fprintf(out,"Hello, world.\n")
isn't "portable" in that the file it generates depends on the
particular character set and EOL sequence of the platform.) If
a program can write something to a file, and then later read the
same file and get the same information, it doesn't really matter
if that file can't be taken to a different platform and read by
the same program compiled on the other platform. (At least not
as far as standard C is concerned. The developer/end-user may
be concerned about data-file portability, but that a different
matter entirely.)

If you use fwrite() to save a float to a binary stream, and later
in the program use fread() on that same stream (assuming that the
file position is the same), aren't you guaranteed to get the same
float value back? (Assuming nothing else has modified the file,
and the fread succeeds, of course.)
Kenny made a good point about it, perhaps not in the best form, but
that's Kenny, "admitted troll it's best to ignore him" as some say. The
OP was very lucky that "regulars" were in good mood, or maybe common
sense worked in this case for some reason. Or perhaps they interpreted
it as "what are strictly-conforming examples of using union", which
is unlikely to be what OP asked about.

I don't think there's anything OT about writing unions to develop
a messaging interface, or other system-specific things like a GUI
interface. Naturally, the implementation of the messages, events,
and GUI itself are OT here, but I don't think an interface to such
things are OT.

For example:

Ignoring the actual GUI specifics, could I use a union of
structs to implement a generic "draw this shape" interface?

Yes, you could to that in 100% "standard C" and be on-topic for
clc.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
Y

Yevgen Muntyan

Kenneth said:
Yevgen Muntyan wrote:
[...]
X events example). It's also true that what your example is
completely off-topic here, even more off-topic than usual, since you
are saving/loading structure content and that's non-portable, breaks
across implementations, may break even on the same implementation, etc.

Just because the data file generated by a particular program is
not portable does not mean that the program itself isn't. (After
all, one could argue that a simple fprintf(out,"Hello, world.\n")
isn't "portable" in that the file it generates depends on the
particular character set and EOL sequence of the platform.) If
a program can write something to a file, and then later read the
same file and get the same information, it doesn't really matter
if that file can't be taken to a different platform and read by
the same program compiled on the other platform. (At least not
as far as standard C is concerned. The developer/end-user may
be concerned about data-file portability, but that a different
matter entirely.)

It may be non-portable even between program invocations. But it's
details. I am *not* trying to argue that you may not talk about
such things here, no way. The problem is that in this newsgroup
the following is totally possible:

Richard Heathfield asks: Why would you use union?
I say: to write and read binary data in my program which draws
pictures.
Richard Heathfield says: Off-topic here therefore irrelevant.
I say: X events example.
Richard Heathfield says: Off-topic here therefore irrelevant.

This one is totally true, there is one fresh thread demonstrating
it.
If you use fwrite() to save a float to a binary stream, and later
in the program use fread() on that same stream (assuming that the
file position is the same), aren't you guaranteed to get the same
float value back? (Assuming nothing else has modified the file,
and the fread succeeds, of course.)

You are, certainly. But if *reason* for doing this doesn't happen
to be likable, you're told you're wrong.
I don't think there's anything OT about writing unions to develop
a messaging interface, or other system-specific things like a GUI
interface. Naturally, the implementation of the messages, events,
and GUI itself are OT here, but I don't think an interface to such
things are OT.

For example:

Ignoring the actual GUI specifics, could I use a union of
structs to implement a generic "draw this shape" interface?

Note that it's not what was asked. Question was about real-life uses
of unions, which *is* off-topic (once some "regular" doesn't happen
to like/need those uses, of course).
Yes, you could to that in 100% "standard C" and be on-topic for
clc.

But you can't provide on-topic reasons for preferring unions over
structs, or preferring union to "normal" way to interpret an object
as character sequence (elsewhere I was told union trick for this
was meant to be UB, that's totally funny thing).

Anyway, please read my post you actually replied to. It wasn't
"it's off-topic here". If it did sound like that, I apologize.
I in no way want to tell what is and what isn't off-topic in
this newsgroup.

Yevgen
 

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,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top