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:
Convert the integer into an array of chars using:
int integer_to_characters(int number, char * buffer)
{
memcpy(buffer, &number, 4);
}
Reverse the order of the chars in that array.
Convert the array of chars back to an integer using:
int characters_to_integer(char * buffer)
{
int result;
memcpy(&result, buffer, 4);
return result;
}
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);
}
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
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With