22

My question is how do you convert a UINT32 value to a UINT8 array[4] (C/C++) preferably in a manner independent of endianness? Additionally, how would you reconstruct the UINT32 value from the UINT8 array[4], to get back to where you started?

1
  • 1
    How do you want to do the conversion? Big-endian or little-endian? Specifically: If your input is 0x12345678, do you want array[0] to be 0x12 or 0x78? You have to decide this for yourself. Then we can help you. Commented Jun 28, 2011 at 15:16

5 Answers 5

42

You haven't really said what you mean by independent of endianness - it's unclear since the byte array must have some endianness. That said, one of the below must answer your requirements:

Given UINT32 v and UINT8 a[4]:

"Host" endian

(use the machine's native byte order):

UINT8 *vp = (UINT8 *)&v; a[0] = vp[0]; a[1] = vp[1]; a[2] = vp[2]; a[3] = vp[3]; 

or:

memcpy(a, &v, sizeof(v)); 

or:

*(UINT32 *)a = v; 

Big endian

(aka "network order"):

a[0] = v >> 24; a[1] = v >> 16; a[2] = v >> 8; a[3] = v; 

Little endian

a[0] = v; a[1] = v >> 8; a[2] = v >> 16; a[3] = v >> 24; 
Sign up to request clarification or add additional context in comments.

4 Comments

Do you have a solution for move semantics? Say you want to move the value of v to the byte array without copying v.
@jiggunjer that makes no sense. Primitive values can't get "moved" like that.
@jiggunjer Yes. If you're talking about C++11 "move semantics" there's nothing to "move" in a 32-bit variable.
I realise this is an old answer (it got liked to by an EE.SE question). But *(UINT32 *)a = v; is a very dangerous assumption - if a is not initialised aligned to a UINT32 word boundary this will likely cause an unaligned access error.
15

E.g. like this:

UINT32 value; UINT8 result[4]; result[0] = (value & 0x000000ff); result[1] = (value & 0x0000ff00) >> 8; result[2] = (value & 0x00ff0000) >> 16; result[3] = (value & 0xff000000) >> 24; 

Edit: added parenthesis (>> seems to have higher precedence than &)

9 Comments

@R.: I disagree. They express the symmetry (I normally have a >> 0 for exactly this purpose), and it would have to be a pretty terrible compiler that wouldn't optimise them away.
Whatever the aesthetic merits of the & operators, the fact is that they kill the code. >> has higher precedence than &.
@R.: Actually, I take that back. I overlooked the fact that we're converting to uint8, so of course, all masks are unnecessary, as @Stephen points out.
And regarding the use of &: You don't only write code for the compiler. You also write code for the one reading the code after you. In my opinion, adding & makes it clear that you take this specific byte, and you don't rely on any behind-your-back truncation. I still think that the compiler is smarter than the one reading the code. So don't make the code readable for the compiler; make it readable for the reader.
You should note that this is little endian.
|
3

If you don't want to code it yourself, you can use the C library function htonl() to convert the 32-bit int to network byte order. There is also the function ntohl() to convert them back to host order.

Once they're in network byte order, it's simply a matter of accessing the int/long as a byte array.

All in all that's are probably the most portable and tested way of achieving your goal.

Comments

2

One could also do it with pointers. (This is little endian, but if you use the same reconstruction method it won't matter)

uint32 in = 0x12345678; uint8 out[4]; *(uint32*)&out = in; 

This assigns the value of the uint32 to the 4 bytes after the memory address of the uint8, doing exactly what you need.

To go the other way:

uint8 in[4] = {0x78, 0x56, 0x34, 0x12}; uint32 out; out = *(uint32*)&in 

1 Comment

I realise this is an old answer (it got liked to by an EE.SE question). But *(uint32*)&out = in; is a very dangerous assumption - if a is not initialised aligned to a uint32 word boundary this will likely cause an unaligned access error on some processors.
-4

use a Union consisting of an Array with 4 time uint8 and an uint32.

So it sorts automatically by c inherent pointer Magic (Arrays are pointers to start of array)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.