排序内存固定字节顺序 Endian

Sorting memory fixing Byte order Endian

我正在努力解决嵌入式系统上的问题。我必须用 C 编程,这对我来说是一项相当大的任务,因为我通常使用基于对象的编程语言工作。 在这个系统中,两个处理器共享内存并且它们以不同的方式处理数据,我很确定这个问题与字节序编码有关,但是在尝试创建一个单一函数来修复这个问题 3 小时失败后,我正在寻求帮助。 我在铸造和指针处理方面苦苦挣扎。

情况: 我在缓冲区中存储了两个(或更多)浮点数(或其他类型)让我们说这个例子是它的{1.0f,1.0f}。 这以 {3F,80,00,00,3F,80,00,00} 的字节表示形式结束 如果另一个处理器重新解释数据,它会根据输入得到负数或高得离谱的指数数。

那么我要达到什么目的呢?修复此顺序的函数,其中 endian 编码被反转。

void fixEncoding(void *StoredData, uint8_t variableSizeInBytes, uint8_t buffer size)

参数将是指向我存储的数据 {3F,80,00,00,3F,80,00,00} 的指针 内编码变量的大小(例如 4 个浮点数或 sizeof(float)) 和存储的数据大小

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}

交换元素中的字节是一个常见的习惯用法:你转到一半的字节并与对称字节交换。您只需要逐个元素地将缓冲区作为字节进行迭代。

代码可以是:

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;
    }
}

首先你需要决定你想要什么样的字节顺序作为公共字节顺序,然后确定缓冲区中的字节是否应该反转。其中一个处理器已经按照这种通用字节顺序存储 floats,因此对于该处理器,您永远不需要反转缓冲区中的字节。

我建议使用网络字节顺序,因为有很多转换 to/from 这种格式的例子。

我在这里使用 htonluint32_t 的主机到网络字节顺序)来确定处理器是否已经在使用此顺序,但还有更有效的方法。参见 C Macro definition to determine big endian or little endian machine?

示例:

#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

这不是 100% 安全的,因为一些不常见的处理器使用混合字节顺序。检查你的没有。