# How to extract bytes from long?

Discussion in 'C Programming' started by RB, Oct 15, 2003.

1. ### RBGuest

How to extract bytes from long, starting from the last byte?
For example, I have a long number:
0x12345678
I need to represent it as the following bytes list:
0x78, 0x56, 0x34, 0x12

Rita

RB, Oct 15, 2003

2. ### Ed MortonGuest

RB wrote:
> How to extract bytes from long, starting from the last byte?
> For example, I have a long number:
> 0x12345678
> I need to represent it as the following bytes list:
> 0x78, 0x56, 0x34, 0x12
>
> Rita

Sounds a bit homework-y, but as a hint try this:

#include <stdio.h>

int main(void)
{
long val=0x12345678;

printf("0x%x\n",val >> 16 & 0xff );

return 0;
}

Regards,

Ed.

Ed Morton, Oct 15, 2003

On Wed, 15 Oct 2003 01:59:04 -0700, RB wrote:

> How to extract bytes from long, starting from the last byte?

#include <stdio.h>

int main() {

unsigned long value = 0x12345678;
int i;

printf("%#lx\n",value);

for (i = sizeof value; i > 0; --i) {
printf("%#x\n", value & 0xff);
value >>= 8;
}
return 0;
}

--
NPV

"the large print giveth, and the small print taketh away"
Tom Waits - Step right up

Nils Petter Vaskinn, Oct 15, 2003
4. ### Thomas StegenGuest

RB wrote:
> How to extract bytes from long, starting from the last byte?
> For example, I have a long number:
> 0x12345678
> I need to represent it as the following bytes list:
> 0x78, 0x56, 0x34, 0x12
>
> Rita

Look at bitwise operators. &, |, ^, <<, >>. Then look up bitmasks
and how to use them and everything should be rather straightforward.

--
Thomas.
"What is the future c existence which does not do in all languages"

Thomas Stegen, Oct 15, 2003
5. ### peteGuest

>
> On Wed, 15 Oct 2003 01:59:04 -0700, RB wrote:
>
> > How to extract bytes from long, starting from the last byte?

>

#include <limits.h>
> #include <stdio.h>
>
> int main() {
>
> unsigned long value = 0x12345678;
> int i;
>
> printf("%#lx\n",value);
>
> for (i = sizeof value; i > 0; --i) {
> printf("%#x\n", value & 0xff);
> value >>= 8;

/*
** You realise that you don't know the size of value,
** so you might as well go all the way.
*/
printf("%#x\n", value & (unsigned char)-1);
value >>= CHAR_BIT;

> }
> return 0;
> }

--
pete

pete, Oct 15, 2003
6. ### peteGuest

pete wrote:
>
> >
> > On Wed, 15 Oct 2003 01:59:04 -0700, RB wrote:
> >
> > > How to extract bytes from long, starting from the last byte?

.... and now for the (sizeof(long)==1) portable way:

/* BEGIN new.c */

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

int main(void)
{
unsigned long value = 0x12345678;
size_t i;

printf("%#lx\n",value);
printf("%#x\n", value & (unsigned char)-1);
for (i = sizeof value - 1; i != 0; --i) {
value >>= CHAR_BIT;
printf("%#x\n", value & (unsigned char)-1);
}
return 0;
}

/* END new.c */

and now for the way which interprets "last byte"
as being the one furthest from ((char*)&value)

/* BEGIN new2.c */

#include <stdio.h>

int main(void)
{
unsigned long value = 0x12345678;
unsigned char *pointer = (unsigned char*)&value + sizeof value;

printf("%#lx\n",value);
do {
--pointer;
printf("%#x\n", (unsigned)*pointer);
} while (pointer != (unsigned char*)&value);
return 0;
}

/* END new2.c */

--
pete

pete, Oct 15, 2003
7. ### John BodeGuest

(RB) wrote in message news:<>...
> How to extract bytes from long, starting from the last byte?
> For example, I have a long number:
> 0x12345678
> I need to represent it as the following bytes list:
> 0x78, 0x56, 0x34, 0x12
>
> Rita

There are a couple of ways. The safest is to use a bitmask (0xFF),
the bitwise & operator, and the >> and << shift operators.
Alternately, you can treat the long as an array of unsigned char by
creating an unsigned char pointer and setting it to the same address
as the long (unsigned char *p = (unsigned char *) &mylong and then
either use array subscript notation to access individual bytes or
"walk" the array by incrementing p, but you have to be aware of
endianness issues (i.e., on a little-endian machine, p[0] would be the
LSB, whereas on a big-endian machine it would be the MSB). The first
method (bitmask and shift) works the same regardless of endian issues.

John Bode, Oct 15, 2003
8. ### Peter NilssonGuest

pete <> wrote in message news:<>...
> pete wrote:
> >
> > Nils Petter Vaskinn wrote:
> > >
> > > On Wed, 15 Oct 2003 01:59:04 -0700, RB wrote:
> > >
> > > > How to extract bytes from long, starting from the last byte?

>
> ... and now for the (sizeof(long)==1) portable way:

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> /* BEGIN new.c */
>
> #include <stdio.h>
> #include <limits.h>
>
> int main(void)
> {
> unsigned long value = 0x12345678;
> size_t i;
>
> printf("%#lx\n",value);
> printf("%#x\n", value & (unsigned char)-1);
> for (i = sizeof value - 1; i != 0; --i) {
> value >>= CHAR_BIT;

UB if sizeof(long) == 1.

value = value >> (CHAR_BIT - 1) >> 1;

> printf("%#x\n", value & (unsigned char)-1);
> }
> return 0;
> }
>
> /* END new.c */

--
Peter

Peter Nilsson, Oct 16, 2003
9. ### CBFalconerGuest

pete wrote:
> > On Wed, 15 Oct 2003 01:59:04 -0700, RB wrote:
> >
> > > How to extract bytes from long, starting from the last byte?

>
> #include <limits.h>
> > #include <stdio.h>
> >
> > int main() {
> >
> > unsigned long value = 0x12345678;
> > int i;
> >
> > printf("%#lx\n",value);
> >
> > for (i = sizeof value; i > 0; --i) {
> > printf("%#x\n", value & 0xff);
> > value >>= 8;

>
> /*
> ** You realise that you don't know the size of value,
> ** so you might as well go all the way.
> */
> printf("%#x\n", value & (unsigned char)-1);
> value >>= CHAR_BIT;
>
> > }
> > return 0;
> > }

You need neither CHAR_BIT nor shifts nor limits.h nor sizeof:

for (i = 8; i > 0; --i) {
printf("%x ", value % 256);
value /= 256;
}
putchar('\n'); /* <--AND HERE is where the \n goes */
return 0;
}

and the result is portable.

--
Chuck F () ()
Available for consulting/temporary embedded and systems.

CBFalconer, Oct 16, 2003
10. ### Samuel BarberGuest

pete <> wrote in message news:<>...
> printf("%#x\n", value & (unsigned char)-1);
> for (i = sizeof value - 1; i != 0; --i) {
> value >>= CHAR_BIT;
> printf("%#x\n", value & (unsigned char)-1);
> }
> return 0;
> }

I would use ~0 for "all 1s" rather than -1.

Sam

Samuel Barber, Oct 16, 2003
11. ### Peter NilssonGuest

(Samuel Barber) wrote in message news:<>...
> pete <> wrote in message news:<>...
> > printf("%#x\n", value & (unsigned char)-1);
> > for (i = sizeof value - 1; i != 0; --i) {
> > value >>= CHAR_BIT;
> > printf("%#x\n", value & (unsigned char)-1);
> > }
> > return 0;
> > }

>
> I would use ~0 for "all 1s" rather than -1.

That risks a trap representation under C99.

--
Peter

Peter Nilsson, Oct 16, 2003
12. ### peteGuest

Peter Nilsson wrote:
>
> pete <> wrote in message news:<>...
> > pete wrote:
> > >
> > > Nils Petter Vaskinn wrote:
> > > >
> > > > On Wed, 15 Oct 2003 01:59:04 -0700, RB wrote:
> > > >
> > > > > How to extract bytes from long, starting from the last byte?

> >
> > ... and now for the (sizeof(long)==1) portable way:

> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >
> > /* BEGIN new.c */
> >
> > #include <stdio.h>
> > #include <limits.h>
> >
> > int main(void)
> > {
> > unsigned long value = 0x12345678;
> > size_t i;
> >
> > printf("%#lx\n",value);
> > printf("%#x\n", value & (unsigned char)-1);
> > for (i = sizeof value - 1; i != 0; --i) {
> > value >>= CHAR_BIT;

>
> UB if sizeof(long) == 1.

No.
If sizeof(long) == 1,
then the loop doesn't execute.

> > printf("%#x\n", value & (unsigned char)-1);
> > }
> > return 0;
> > }
> >
> > /* END new.c */

--
pete

pete, Oct 17, 2003
13. ### Samuel BarberGuest

(Peter Nilsson) wrote in message news:<>...
> (Samuel Barber) wrote in message news:<>...
> > pete <> wrote in message news:<>...
> > > printf("%#x\n", value & (unsigned char)-1);
> > > for (i = sizeof value - 1; i != 0; --i) {
> > > value >>= CHAR_BIT;
> > > printf("%#x\n", value & (unsigned char)-1);
> > > }
> > > return 0;
> > > }

> >
> > I would use ~0 for "all 1s" rather than -1.

>
> That risks a trap representation under C99.

Nonsense. ~0 is idiomatic C. Aren't you worried about the "risk" that
-1 may not be implemented as all-1s? That is, after all, an
implementation detail. It's not true for sign-magnitude or 1's
complement, for example.

Sam

Samuel Barber, Oct 17, 2003
14. ### peteGuest

CBFalconer wrote:
>
> pete wrote:
> > Nils Petter Vaskinn wrote:
> > > On Wed, 15 Oct 2003 01:59:04 -0700, RB wrote:
> > >
> > > > How to extract bytes from long, starting from the last byte?

> >
> > #include <limits.h>
> > > #include <stdio.h>
> > >
> > > int main() {
> > >
> > > unsigned long value = 0x12345678;
> > > int i;
> > >
> > > printf("%#lx\n",value);
> > >
> > > for (i = sizeof value; i > 0; --i) {
> > > printf("%#x\n", value & 0xff);
> > > value >>= 8;

> >
> > /*
> > ** You realise that you don't know the size of value,
> > ** so you might as well go all the way.
> > */
> > printf("%#x\n", value & (unsigned char)-1);
> > value >>= CHAR_BIT;
> >
> > > }
> > > return 0;
> > > }

>
> You need neither CHAR_BIT nor shifts nor limits.h nor sizeof:
>
> for (i = 8; i > 0; --i) {
> printf("%x ", value % 256);
> value /= 256;
> }
> putchar('\n'); /* <--AND HERE is where the \n goes */
> return 0;
> }
>
> and the result is portable.

I was addressing the more general subject,
in the subject line of this thread: "How to extract bytes from long?",
rather than how to extract bytes from 0x12345678
or any other number which doesn't require more than 32 bits.

--
pete

pete, Oct 17, 2003
15. ### peteGuest

Samuel Barber wrote:
>
> (Peter Nilsson) wrote in message news:<>...
> > (Samuel Barber) wrote in message news:<>...
> > > pete <> wrote in message news:<>...
> > > > printf("%#x\n", value & (unsigned char)-1);
> > > > for (i = sizeof value - 1; i != 0; --i) {
> > > > value >>= CHAR_BIT;
> > > > printf("%#x\n", value & (unsigned char)-1);
> > > > }
> > > > return 0;
> > > > }
> > >
> > > I would use ~0 for "all 1s" rather than -1.

> >
> > That risks a trap representation under C99.

>
> Nonsense. ~0 is idiomatic C. Aren't you worried about the "risk" that
> -1 may not be implemented as all-1s? That is, after all, an
> implementation detail. It's not true for sign-magnitude or 1's
> complement, for example.

~0 is negative zero in ones complement.
Implementations are allowed trap negative zero.

-1 is a value, not a bit pattern.
The value of negative one, cast to unsigned char, is UCHAR_MAX.

--
pete

pete, Oct 17, 2003
16. ### Sheldon SimmsGuest

On Fri, 17 Oct 2003 02:44:03 +0000, pete wrote:

> Samuel Barber wrote:
>>
>> (Peter Nilsson) wrote in message news:<>...
>> > (Samuel Barber) wrote in message news:<>...
>> > > pete <> wrote in message news:<>...
>> > > > printf("%#x\n", value & (unsigned char)-1);
>> > > > for (i = sizeof value - 1; i != 0; --i) {
>> > > > value >>= CHAR_BIT;
>> > > > printf("%#x\n", value & (unsigned char)-1);
>> > > > }
>> > > > return 0;
>> > > > }
>> > >
>> > > I would use ~0 for "all 1s" rather than -1.
>> >
>> > That risks a trap representation under C99.

>>
>> Nonsense. ~0 is idiomatic C. Aren't you worried about the "risk" that
>> -1 may not be implemented as all-1s? That is, after all, an
>> implementation detail. It's not true for sign-magnitude or 1's
>> complement, for example.

>
>
> ~0 is negative zero in ones complement.
> Implementations are allowed trap negative zero.

~0u cannot be a trap representation, however.

6.5.3.3
4 The result of the ~ operator is the bitwise complement of its
(promoted) operand ... If the promoted type is an unsigned type,
the expression ~E is equivalent to the maximum value representable
in that type minus E.

> -1 is a value, not a bit pattern.
> The value of negative one, cast to unsigned char, is UCHAR_MAX.

Sheldon Simms, Oct 17, 2003
17. ### Samuel BarberGuest

pete <> wrote in message news:<>...
> Samuel Barber wrote:
> >
> > (Peter Nilsson) wrote in message news:<>...
> > > (Samuel Barber) wrote in message news:<>...
> > > > pete <> wrote in message news:<>...
> > > > > printf("%#x\n", value & (unsigned char)-1);
> > > > > for (i = sizeof value - 1; i != 0; --i) {
> > > > > value >>= CHAR_BIT;
> > > > > printf("%#x\n", value & (unsigned char)-1);
> > > > > }
> > > > > return 0;
> > > > > }
> > > >
> > > > I would use ~0 for "all 1s" rather than -1.
> > >
> > > That risks a trap representation under C99.

> >
> > Nonsense. ~0 is idiomatic C. Aren't you worried about the "risk" that
> > -1 may not be implemented as all-1s? That is, after all, an
> > implementation detail. It's not true for sign-magnitude or 1's
> > complement, for example.

>
>
> ~0 is negative zero in ones complement.
> Implementations are allowed trap negative zero.

You're just repeating words, without any understanding. There's no
such thing as "negative zero" (or negative anything) in the context of
bitwise operations. How can a bitwise operation trap? It can't.

> -1 is a value, not a bit pattern.
> The value of negative one, cast to unsigned char, is UCHAR_MAX.

Hello? The point is that -1 is ***being used as*** a bit pattern. The
intent is to get "all 1s", which is true if the integer representation
is 2's complement; that's an implicit assumption of the code. (This is
the best reason not to use -1: the intent is not perfectly clear).

Sam

Samuel Barber, Oct 17, 2003
18. ### Arthur J. O'DwyerGuest

On Fri, 16 Oct 2003, Samuel Barber wrote:
>
> pete wrote in message news:<>...
> > Samuel Barber wrote:
> > > (Peter Nilsson) wrote...
> > > > Samuel Barber wrote...
> > > > > pete wrote in message news:<>...
> > > > > >
> > > > > > printf("%#x\n", value & (unsigned char)-1);
> > > > >
> > > > > I would use ~0 for "all 1s" rather than -1.
> > > >
> > > > That risks a trap representation under C99.
> > >
> > > Nonsense. ~0 is idiomatic C. Aren't you worried about the "risk" that
> > > -1 may not be implemented as all-1s? That is, after all, an
> > > implementation detail. It's not true for sign-magnitude or 1's
> > > complement, for example.

> >
> > You're wrong about everything.
> >
> > ~0 is negative zero in ones complement.
> > Implementations are allowed trap negative zero.

>
> You're just repeating words, without any understanding. There's no
> such thing as "negative zero" (or negative anything) in the context of
> bitwise operations.

It is AFAIK implementation-defined whether the concept of "negative
zero" is meaningful in standard C (depending on the representation
of signed integers).

> How can a bitwise operation trap? It can't.

Of course it can! (Why wouldn't it? And do modern digital computers
perform any operations that *aren't* bitwise, anyway?)

> > -1 is a value, not a bit pattern.
> > The value of negative one, cast to unsigned char, is UCHAR_MAX.

To clarify pete's point:

(uchar)-1 == (uchar)-((int)1) == (-(int)1)+UCHAR_MAX == UCHAR_MAX-1

....which is guaranteed to have an all-ones bit pattern, regardless

> Hello? The point is that -1 is ***being used as*** a bit pattern.

Then it's being used incorrectly. -1 is *not* a bit pattern, it's
an integer expression equal to the additive inverse of the integer 1.
It doesn't have a "bit pattern" per se.

> The intent is to get "all 1s", which is true if the integer
> representation is 2's complement; that's an implicit assumption
> of the code.

If that *were* an implicit assumption of the code, then the code
would be broken. But it's not. Pete's code AFAICT doesn't assume
anything earth-shattering about the integer representations used
by the target system.

> (This is the best reason not to use -1: the intent is not
> perfectly clear).

However, it *does* produce the right answer, which is a point in
its favor. ~0 might trap, and in any case I think (unsigned char)-1
has a bit more aesthetic value to it (YMMV, of course).

And if you want everything to be *perfectly* clear, then you might
want to consider a different programming language. C is just
full of 'for (i=0; a; ++i)'s and 'while (*s++ = *t++)'s; if
a simple -1 throws you, then you're in trouble.

-Arthur

Arthur J. O'Dwyer, Oct 17, 2003
19. ### Sheldon SimmsGuest

On Thu, 16 Oct 2003 23:53:05 -0700, Samuel Barber wrote:

> pete <> wrote in message news:<>...
>> Samuel Barber wrote:
>> >
>> > (Peter Nilsson) wrote in message news:<>...
>> > > (Samuel Barber) wrote in message news:<>...
>> > > > pete <> wrote in message news:<>...
>> > > > > printf("%#x\n", value & (unsigned char)-1);
>> > > > > for (i = sizeof value - 1; i != 0; --i) {
>> > > > > value >>= CHAR_BIT;
>> > > > > printf("%#x\n", value & (unsigned char)-1);
>> > > > > }
>> > > > > return 0;
>> > > > > }
>> > > >
>> > > > I would use ~0 for "all 1s" rather than -1.
>> > >
>> > > That risks a trap representation under C99.
>> >
>> > Nonsense. ~0 is idiomatic C. Aren't you worried about the "risk" that
>> > -1 may not be implemented as all-1s? That is, after all, an
>> > implementation detail. It's not true for sign-magnitude or 1's
>> > complement, for example.

>>
>>
>> ~0 is negative zero in ones complement.
>> Implementations are allowed trap negative zero.

>
> You're just repeating words, without any understanding. There's no
> such thing as "negative zero" (or negative anything) in the context of
> bitwise operations. How can a bitwise operation trap? It can't.

6.2.6.2 Integer types
2 ... (It is implementation-defined) whether the value with ...
sign bit 1 and all value bits 1 (for one's complement), is a trap
representation or a normal value. In the case of ... one's
complement, if this representation is a normal value it is called
a negative zero.
...
3 If the implementation supports negative zeros, they shall be
generated only by: the &, |, ^, ~, <<, and >> operators with
arguments that produce such a value;
...
4 If the implementation does not support negative zeros, the
behavior of the &, |, ^, ~, <<, and >> operators with arguments
that would produce such a value is undefined.

Sheldon Simms, Oct 17, 2003
20. ### Jirka KlaueGuest

Arthur J. O'Dwyer wrote:
....
> (uchar)-1 == (uchar)-((int)1) == (-(int)1)+UCHAR_MAX == UCHAR_MAX-1

You must have miscalculated somewhere. (uc)-1 should be UCHAR_MAX.

(uc)-1 == (uc)(0 - 1) == (uc)(UINT_MAX + 1 - 1) == (uc)(UINT_MAX) == UCHAR_MAX

Jirka

Jirka Klaue, Oct 17, 2003