Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I reorder the bytes of an integer? [duplicate]

My task is to convert a data file from big endian to little endian & vice versa using C. I have been looking online for about 3 hours now for other examples and reading my text book, however I am so stuck on how to even start this function.

So far I have the order of events correct (1 through 4) but inside my convert_and_save function do I have to create a char array using → char buffer[4];?

Can someone please help me? even if you just give me clues on what to look up, I would greatly appreciate it.

I need to write a function called:

void convert_and_save(struct record item, FILE * output_handle, int number);

inside this function I do the following series of steps:

  1. Convert the integer into an array of chars using:

    int integer_to_characters(int number, char * buffer)
    {
       memcpy(buffer, &number, 4);
    }
    
  2. Reverse the order of the chars in that array.

  3. Convert the array of chars back to an integer using:

    int characters_to_integer(char * buffer)
    {
       int result;
       memcpy(&result, buffer, 4);
       return result;
    }
    
  4. write the converted record on the output file using:

    void save_record(FILE * file_handle, struct record a)
    {
       char output_buffer[size_of_record];
       integer_to_characters(a.age, &(output_buffer[0]));
       memcpy(&(output_buffer[4]), a.name, 12);
       integer_to_characters(a.department, &(output_buffer[16]));
       fwrite(output_buffer, sizeof(char), size_of_record, file_handle);
    }
    
like image 648
mrsj Avatar asked Jul 21 '14 02:07

mrsj


2 Answers

These are not standard function (these are gcc extensions), but you may be able to use them:

— Built-in Function: uint16_t __builtin_bswap16 (uint16_t x) Returns x with the order of the bytes reversed; for example, 0xaabb becomes 0xbbaa. Byte here always means exactly 8 bits.

— Built-in Function: uint32_t __builtin_bswap32 (uint32_t x) Similar to __builtin_bswap16, except the argument and return types are 32 bit.

— Built-in Function: uint64_t __builtin_bswap64 (uint64_t x) Similar to __builtin_bswap32, except the argument and return types are 64 bit.

If you can use these, chances are it will result in more optimal code for your platform, if not, good job, submit a patch to gcc :)

Clang also has __builtin_bswap16() __builtin_bswap32() __builtin_bswap64()

Visual Studio

unsigned short _byteswap_ushort (
   unsigned short val
);
unsigned long _byteswap_ulong (
   unsigned long val
);
unsigned __int64 _byteswap_uint64 (
   unsigned __int64 val
);

ICC has _bswap16, _bswap and _bswap64 *need further reference

like image 185
technosaurus Avatar answered Sep 26 '22 08:09

technosaurus


This one of the functions I wrote for the Parrot VM, you can download byteorder.c from parrotcode.org. There are probably shorter ways to do it, but this works for different size integers, and we had a macro to detect the byteorder of the platform in PARROT_BIGENDIAN, you can discard all that. Also, as mentioned above, you can search out htonl() which is a nop on bigendian hardware, but converts on little endian (just grab a Linux x86 implementation)

INTVAL
fetch_iv_le(INTVAL w)
{
    ASSERT_ARGS(fetch_iv_le)
#if !PARROT_BIGENDIAN
    return w; // No-op on little endian hardware
#else
#  if INTVAL_SIZE == 4
    return (w << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | (w >> 24);
#  else
#    if INTVAL_SIZE == 8
    INTVAL r;

    r = w << 56;
    r |= (w & 0xff00) << 40;
    r |= (w & 0xff0000) << 24;
    r |= (w & 0xff000000) << 8;
    r |= (w & 0xff00000000) >> 8;
    r |= (w & 0xff0000000000) >> 24;
    r |= (w & 0xff000000000000) >> 40;
    r |= (w & 0xff00000000000000) >> 56;
    return r;
#    endif
#  endif
#endif
}
like image 41
codenheim Avatar answered Sep 24 '22 08:09

codenheim