Sorting memory fixing Byte order Endian
I am struggeling with a problem on an embedded system. I have to program in C which is quite the task for me as i usualy work in object based programming languages. In this system two processors share memory and they handle data differntly, i am pretty sure the issue has to do with endian encoding, but after 3 hours of failed attempts to make a single function to fix this i am seeking for help. I struggle immensly with casting and and pointer handeling.
The situation: I store two (or more) floats (or other types) in a buffer lets say for this example its {1.0f , 1.0f}. This ends up with the byte representation of {3F,80,00,00,3F,80,00,00} if the other processor reinterprets the data it gets negative or rediculously high exponential numbers depending on the input.
So what am i trying to achive? A function that fixes this order where the endian encoding is reversed.
void fixEncoding(void *StoredData, uint8_t variableSizeInBytes, uint8_t buffer size)
The parameters would be a pointer to my stored data {3F,80,00,00,3F,80,00,00} the size of the variables encoded within (4 for a float for example or sizeof(float)) and the stored datas size
input {3F,80,00,00,3F,80,00,00} , 4, 8
output{00,00,80,3F,00,00,80,3F}
input {3F,80,00,00,3F,80,00,00} , 2, 8
output{80,3f,00,00,80,3f,00,00}
Swapping bytes in an element is a common idiom: you go up to the half of the bytes and exchange with the symetric byte. You just have to iterate your buffer as bytes, element by element.
Code could be:
void fixEncoding(void* StoredData, uint8_t variableSizeInBytes, uint8_t buffer_size) {
char* data = StoredData; // must be char to be able to use pointer arithmetics
while (buffer_size > 0) {
int i;
// swap the element at data
for (i = 0; i < variableSizeInBytes / 2; i++) {
int j = variableSizeInBytes - i - 1;
char t = data[i];
data[i] = data[j];
data[j] = t;
}
// skip to next element
data += variableSizeInBytes;
buffer_size -= variableSizeInBytes;
}
}
First you need to decide on what byte order you want to be the common byte order and then determine if the bytes in the buffer should be reversed. One of the processors already store float
s in this common byte order so for that processor, you never need to reverse the bytes in the buffer.
I suggest using network byte order just because there are lots of examples of converting to/from that format.
I'm here using htonl
(host to network byte order for uint32_t
) to determine if the processor is already using this order, but there are more effective ways. See C Macro definition to determine big endian or little endian machine?.
Example:
#include <arpa/inet.h> // htonl
void swap_uint8_t(char *a, char *b) { // swap two bytes
uint8_t tmp = *a;
*a = *b;
*b = tmp;
}
void reverse(void *data, size_t len) { // reverse one `float` (or whatever you have)
uint8_t *s = data;
uint8_t *e = s + len;
for(;s < e--; ++s) {
swap_uint8_t(s, e);
}
}
void fixEncoding(void *StoredData, uint8_t variableSizeInBytes, uint8_t buffer_size) {
if(htonl(1) != 1) { // determine if this machine is not using network byte order
// not network byte order, reverse each `float` (or whatever you have)
uint8_t *data = StoredData;
for(uint8_t pos = 0; pos < buffer_size; pos += variableSizeInBytes) {
reverse(data + pos, variableSizeInBytes);
}
}
}
Demo
This is not 100% safe since some uncommon processors uses mixed endianess. Check that yours don't.