How to extract bytes from a long?

C

Curt Geske

I'm suprised no one suggested a union!

#include <stdio.h>
union _x
{
long lng;
char byt[4];
} X;

void main( void )
{
int i; // Always need an 'i', ...
long val = 0x12345678;

X.lng = val;
for( i = 3; i >= 0; i-- )
{
printf( "%#02x\n", X.byt );
}


} // main
 
C

Chris Dollin

Curt said:
I'm suprised no one suggested a union!

#include <stdio.h>
union _x
{
long lng;
char byt[4];
} X;

void main( void )
{
int i; // Always need an 'i', ...
long val = 0x12345678;

X.lng = val;
for( i = 3; i >= 0; i-- )
{
printf( "%#02x\n", X.byt );
}


} // main


We wanted solutions that didn't exhibit undefined behaviour, ta very
much. Or even unspecified behaviour - like, is X.byt[0] 0x12 or 0x78
or 0x34 or 0x56, and why?
 
I

Irrwahn Grausewitz

If you want to reply to a post, please use the "Reply" function of your
newsreader and do not start a new thread. Thank you.
I'm suprised no one suggested a union!

#include <stdio.h>
union _x
{
long lng;
char byt[4];

Stop right here: what makes you think a long is four chars wide?

<SNIP>

Regards
 
S

Serve La

Irrwahn Grausewitz said:
I'm suprised no one suggested a union!

#include <stdio.h>
union _x
{
long lng;
char byt[4];

Stop right here: what makes you think a long is four chars wide?

That could be easily overcome with sizeof. It's more that you can't rely on
the byte order if you try to do it portably.
 
D

David Rubin

Serve said:
Irrwahn Grausewitz said:
I'm suprised no one suggested a union!

#include <stdio.h>
union _x
{
long lng;
char byt[4];

Stop right here: what makes you think a long is four chars wide?

That could be easily overcome with sizeof. It's more that you can't rely on
the byte order if you try to do it portably.

No, the problem is that you can't write into one union field and read
from another.

/david
 
M

Martin Ambuhl

Curt said:
I'm suprised no one suggested a union!

Since your suggestion involves non-portable implementation-defined behavior
(in addition to the obvious illiteracy for the return type for main), I'm
surprised that anyone would suggest it.
#include <stdio.h>
union _x
{
long lng;
char byt[4];
} X;

void main( void )

I'm surprised you have the gall to write the above line. Please wake up.
Your nap is now at least 14 years long.
{
int i; // Always need an 'i', ...
long val = 0x12345678;

X.lng = val;
for( i = 3; i >= 0; i-- )
{
printf( "%#02x\n", X.byt );
}


Try the following on for size. Not that "the most recent store" was to the
'.lng' member, which is different from the '.byt' member.

[#5] With one exception, if the value of a member of a union
object is used when the most recent store to the object was
to a different member, the behavior is
implementation-defined.70) One special guarantee is made in
order to simplify the use of unions: If a union contains
several structures that share a common initial sequence (see
below), and if the union object currently contains one of
these structures, it is permitted to inspect the common
initial part of any of them anywhere that a declaration of
the completed type of the union is visible. Two structures
share a common initial sequence if corresponding members
have compatible types (and, for bit-fields, the same widths)
for a sequence of one or more initial members.
 
E

Eric Sosman

cody said:
#include <stdio.h>
union _x
{
long lng;
char byt[4];

Stop right here: what makes you think a long is four chars wide?

#include <stdio.h>
union _x
{
long lng;
char byt[sizeof long];
}

better?

Marginally. It still doesn't address the issue raised
by both David Rubin and Martin Ambuhl, and it still uses
an identifier reserved for the implementation, and it still
risks trouble with trap representations or if the system
uses signed magnitude or ones' complement arithmetic ...

... but other than that, Mrs. Lincoln, how did you
like the play?
 
C

cody

I'm suprised no one suggested a union!
#include <stdio.h>
union _x
{
long lng;
char byt[4];

Stop right here: what makes you think a long is four chars wide?

That could be easily overcome with sizeof. It's more that you can't rely on
the byte order if you try to do it portably.

No, the problem is that you can't write into one union field and read
from another.


Isn't that what a union is good for???
 
C

Christian Bau

I'm suprised no one suggested a union!

#include <stdio.h>
union _x
{
long lng;
char byt[4];

Stop right here: what makes you think a long is four chars wide?

That could be easily overcome with sizeof. It's more that you can't rely on
the byte order if you try to do it portably.

No, the problem is that you can't write into one union field and read
from another.


Isn't that what a union is good for???[/QUOTE]

Stay with freeware. Don't even think about getting a paid job as a
programmer.
 
C

cody

David Rubin said:
Serve said:
Irrwahn Grausewitz said:
I'm suprised no one suggested a union!

#include <stdio.h>
union _x
{
long lng;
char byt[4];

Stop right here: what makes you think a long is four chars wide?

That could be easily overcome with sizeof. It's more that you can't rely on
the byte order if you try to do it portably.

No, the problem is that you can't write into one union field and read
from another.

With one exception, which is valid in this case:

[#5] With one exception, if the value of a member of a union
object is used when the most recent store to the object was
to a different member, the behavior is
implementation-defined.70)

<<< look here below! >>>
One special guarantee is made in
order to simplify the use of unions: If a union contains
several structures that share a common initial sequence (see
below), and if the union object currently contains one of
these structures, it is permitted to inspect the common
initial part of any of them anywhere that a declaration of
the completed type of the union is visible. Two structures
share a common initial sequence if corresponding members
have compatible types (and, for bit-fields, the same widths)
for a sequence of one or more initial members.
 
J

Jeremy Yallop

Eric said:
cody said:
#include <stdio.h>
union _x
{
long lng;
char byt[4];

Stop right here: what makes you think a long is four chars wide?

#include <stdio.h>
union _x
{
long lng;
char byt[sizeof long];
}

better?

Marginally. It still doesn't address the issue raised
by both David Rubin and Martin Ambuhl, and it still uses
an identifier reserved for the implementation, and it still
risks trouble with trap representations or if the system
uses signed magnitude or ones' complement arithmetic ...

For completeness, there's also a syntax error.

Jeremy.
 
C

cody

#include said:
union _x
{
long lng;
char byt[sizeof long];
}

better?

Marginally. It still doesn't address the issue raised
by both David Rubin and Martin Ambuhl, and it still uses
an identifier reserved for the implementation,

What reserved identifier? Do you mean the underscore before x?
and it still
risks trouble with trap representations or if the system
uses signed magnitude or ones' complement arithmetic ...

He just wanted to extract the bytes of a long. Sometimes you do not care how
the
bytes are represented are in that long, just getting them is enough.

You should not assign new values to byt, that could cause trap
representations as you said, but reading is allowed and safe.
... but other than that, Mrs. Lincoln, how did you
like the play?

What do you mean with that?
 
C

cody

#include said:
union _x
{
long lng;
char byt[sizeof long];
}

better?

Marginally. It still doesn't address the issue raised
by both David Rubin and Martin Ambuhl, and it still uses
an identifier reserved for the implementation, and it still
risks trouble with trap representations or if the system
uses signed magnitude or ones' complement arithmetic ...

For completeness, there's also a syntax error.


The missing semicolon at the end?
 
I

Irrwahn Grausewitz

cody said:
David Rubin said:
Serve said:
I'm suprised no one suggested a union!

#include <stdio.h>
union _x
{
long lng;
char byt[4];

Stop right here: what makes you think a long is four chars wide?

That could be easily overcome with sizeof. It's more that you can't rely on
the byte order if you try to do it portably.

No, the problem is that you can't write into one union field and read
from another.

With one exception, which is valid in this case:

What makes you think so? Implementation defined means "not portable"
and there are no structs in the union, so why should ISO/IEC 9899:1999
6.5.2.3#5 be applicable in this case?

BTW, you should name version, chapter & verse if you quote a standard
(or a draft version of it, like you did).

<6.5.2.3#5 snipped>

Regards
 
I

Irrwahn Grausewitz

cody said:
#include <stdio.h>
union _x
{
long lng;
char byt[sizeof long];
}

better?

Marginally. It still doesn't address the issue raised
by both David Rubin and Martin Ambuhl, and it still uses
an identifier reserved for the implementation, and it still
risks trouble with trap representations or if the system
uses signed magnitude or ones' complement arithmetic ...

For completeness, there's also a syntax error.

The missing semicolon at the end?

Actually, there are two syntax errors, of which the
missing semicolon is one.
 
R

Richard Heathfield

cody said:
#include <stdio.h>
union _x
{
long lng;
char byt[sizeof long];
}

better?

Marginally. It still doesn't address the issue raised
by both David Rubin and Martin Ambuhl, and it still uses
an identifier reserved for the implementation, and it still
risks trouble with trap representations or if the system
uses signed magnitude or ones' complement arithmetic ...

For completeness, there's also a syntax error.


The missing semicolon at the end?

That's one. There's another.
 
M

Mark Gordon

#include <stdio.h>
union _x
{
long lng;
char byt[sizeof long];
}

better?

Marginally. It still doesn't address the issue raised
by both David Rubin and Martin Ambuhl, and it still uses
an identifier reserved for the implementation,

What reserved identifier? Do you mean the underscore before x?

_x is reserved, yes. Unless you fully understand the rules as to which
identifiers are reserved in what scope you should avoid starting any
identifier with an underscore.
He just wanted to extract the bytes of a long. Sometimes you do not
care how the
bytes are represented are in that long, just getting them is enough.

You should not assign new values to byt, that could cause trap
representations as you said, but reading is allowed and safe.

No it isn't. You have been told in another post that it is not.

[Freeware, Games and Humor]

If the freeware is written by you in C then it is probably worth far
less than it costs.
 
J

Joe Wright

cody said:
#include <stdio.h>
union _x
{
long lng;
char byt[sizeof long];
}

better?

Marginally. It still doesn't address the issue raised
by both David Rubin and Martin Ambuhl, and it still uses
an identifier reserved for the implementation,

What reserved identifier? Do you mean the underscore before x?
and it still
risks trouble with trap representations or if the system
uses signed magnitude or ones' complement arithmetic ...

He just wanted to extract the bytes of a long. Sometimes you do not care how
the
bytes are represented are in that long, just getting them is enough.

You should not assign new values to byt, that could cause trap
representations as you said, but reading is allowed and safe.
... but other than that, Mrs. Lincoln, how did you
like the play?

What do you mean with that?

Cody,

They might be picking on you now. I'll move tentatively to your side.

This snippet fixes your remaining syntax error (you'll see it easily)
but provides fodder for our detractors.

I contend, as you seem to, that accessing u.lng as components of u.byt[]
is what unions are all about. We could be wrong.

Accessing memory through (unsigned char *) seems to be guaranteed to
work. I demonstrate both methods below. I don't understand why the first
is wrong while the second is right. Duck! :)

#include <stdio.h>

typedef unsigned long ulong;
typedef unsigned char uchar;

union {
ulong lng;
uchar byt[ sizeof (ulong) ];
} u;

int main(void) {
int i, j = sizeof (ulong);
uchar *ucr = (uchar *)&u.lng;
u.lng = 0x12345678;
for (i = 0; i < j; ++i)
printf(" 0x%02X", u.byt);
puts("");
for (i = 0; i < j; ++i)
printf(" 0x%02X", ucr);
return 0;
}
 
I

Irrwahn Grausewitz

Joe Wright said:
cody said:
#include <stdio.h>
union _x
{
long lng;
char byt[sizeof long];
}

better?
I contend, as you seem to, that accessing u.lng as components of u.byt[]
is what unions are all about. We could be wrong.

As I understand it, the main purpose of unions is to make it possible
to define objects of a "generic" type that can hold values of different
types, one at a time. It was not introduced to the language to have
a convenient way of interpreting the same data (the implementations
internal representation of a value) in different ways by writing to one
union member and reading from another.

Moral: you write a long, you read a long. ;-)

Regards
 

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,744
Messages
2,569,480
Members
44,900
Latest member
Nell636132

Latest Threads

Top