Convert Little Endian to Big Endian

Assuming what you need is a simple byte swap, try something like

Unsigned 16 bit conversion:

swapped = (num>>8) | (num<<8);

Unsigned 32-bit conversion:

swapped = ((num>>24)&0xff) | // move byte 3 to byte 0
                    ((num<<8)&0xff0000) | // move byte 1 to byte 2
                    ((num>>8)&0xff00) | // move byte 2 to byte 1
                    ((num<<24)&0xff000000); // byte 0 to byte 3

This swaps the byte orders from positions 1234 to 4321. If your input was 0xdeadbeef, a 32-bit endian swap might have output of 0xefbeadde.

The code above should be cleaned up with macros or at least constants instead of magic numbers, but hopefully it helps as is

EDIT: as another answer pointed out, there are platform, OS, and instruction set specific alternatives which can be MUCH faster than the above. In the Linux kernel there are macros (cpu_to_be32 for example) which handle endianness pretty nicely. But these alternatives are specific to their environments. In practice endianness is best dealt with using a blend of available approaches

 

OR

Endian conversion works at the bit and 8-bit byte level. Most endian issues deal with the byte level. OP code is doing a endian change at the 4-bit nibble level. Recommend instead:

// Swap endian (big to little) or (little to big)
uint32_t num = 9;
uint32_t b0,b1,b2,b3;
uint32_t res;

b0 = (num & 0x000000ff) << 24u;
b1 = (num & 0x0000ff00) << 8u;
b2 = (num & 0x00ff0000) >> 8u;
b3 = (num & 0xff000000) >> 24u;

res = b0 | b1 | b2 | b3;

printf("%" PRIX32 "\n", res);

If performance is truly important, the particular processor would need to be known. Otherwise, leave it to the compiler.

[Edit] OP added a comment that changes things.
“32bit numerical value represented by the hexadecimal representation (st uv wx yz) shall be recorded in a four-byte field as (st uv wx yz).”

It appears in this case, the endian of the 32-bit number is unknown and the result needs to be store in memory in little endian order.

uint32_t num = 9;
uint8_t b[4];
b[0] = (uint8_t) (num >>  0u);
b[1] = (uint8_t) (num >>  8u);
b[2] = (uint8_t) (num >> 16u);
b[3] = (uint8_t) (num >> 24u);

[2016 Edit] Simplification

… The type of the result is that of the promoted left operand…. Bitwise shift operators C11 §6.5.7 3

Using a u after the shift constants (right operands) results in the same as without it.

b3 = (num & 0xff000000) >> 24u;
b[3] = (uint8_t) (num >> 24u);
// same as 
b3 = (num & 0xff000000) >> 24;
b[3] = (uint8_t) (num >> 24);

 

in QNX use following:

ENDIAN_BE16()

Return a big-endian 16-bit value in native format

Synopsis:

#include <gulliver.h>

uint16_t ENDIAN_BE16( uint16_t num );

Arguments:

num
The big-endian number you want to convert.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The ENDIAN_BE16() macro returns the native version of the big-endian value num.

Returns:

The native-endian value of num.

Examples:

Convert a big-endian value to native-endian:

#include <stdio.h>
#include <stdlib.h>
#include <gulliver.h>
#include <inttypes.h>

int main( void )
{
    uint16_t val = 0x1234;
    
    printf( "0x%04x = 0x%04x\n",
            val, ENDIAN_BE16( val ) );

    return EXIT_SUCCESS;
}

On a little-endian system, this prints:

0x1234 = 0x3412

 

 

 

 

Ref.:

http://stackoverflow.com/questions/2182002/convert-big-endian-to-little-endian-in-c-without-using-provided-func

http://stackoverflow.com/questions/19275955/convert-little-endian-to-big-endian

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s