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:
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
ICC has
_bswap16, _bswap and _bswap64
*need further referenceYou may want to have a look at this answer, which shows how to convert both ways, also with different byte sizes. This is one way to do it, but more efficient ways are discussed in the thread linked.
This is my sample. It reverses the endianess of an integer. Notice that C doesn't specify the size of int. It could be 16, 32, 64 ... Using the (uint_16t, uint_32t, uint_64t) instead if you want to ensure the size,
Take a look at this answer: https://stackoverflow.com/a/105339/1461424
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)