C ++ 11:endian转换

时间:2016-02-22 14:14:15

标签: templates c++11 endianness data-conversion

我试图在编译时获得系统字节编码(endian),以便在主机端和网络端之间进行转换整数(大于32位)的模板特化。不幸的是,我没有找到一个可以在编译时使用C ++ 11并且没有外部库(例如boost)的工作解决方案。

我决定为大小超过32位的(无符号)整数编写一般代码,它似乎可以在我的本地机器上运行:

#include <climits>
#include <cstdint>
#include <iostream>

template<typename T>
T host_to_network(const T& value) {
    char tmp[sizeof(T)];
    size_t i, shift = 0;
    for (size_t i = 0; i < sizeof(T); ++i) {
        tmp[sizeof(T) - 1 - i] = (value >> shift) & 0xFF;
        shift += CHAR_BIT;
    }
    return *reinterpret_cast<const T *>(tmp);
}

template<typename T>
T network_to_host(const T& value) {
    char tmp[sizeof(T)];
    *reinterpret_cast<T *>(tmp) = value;
    size_t shift = 0;
    T result;
    for (size_t i = 0; i < sizeof(T); ++i) {
        result |= tmp[sizeof(T) - 1 - i] << shift;
        shift += CHAR_BIT;
    }
    return result;
}

int main() {
    uint32_t xxx = 1234;
    //int16_t xxx = -12;
    std::cout << host_to_network(xxx) << std::endl;
    std::cout << network_to_host(xxx) << std::endl;
    std::cout << host_to_network(network_to_host(xxx)) << std::endl;
}

不幸的是,我不确定这是否适用于任何架构,或者至少适用于具有小端和大端的主机。我的电脑使用小端,它似乎在这里工作。有没有人在代码中看到错误?或者有人可以用big endian检查它吗?

对于签名整数,代码不起作用,但我不知道为什么。有人能给我一个暗示吗?

我知道如果host endian等于本地endian,这段代码很慢,但这对我的用例来说没问题。

非常感谢

祝你好运

凯文

1 个答案:

答案 0 :(得分:1)

易于识别和转换。 这是一个如此频繁的操作 经常通过检测循环和移位来完成 我觉得我应该提供这种方法 我已经使用了十多年 供其他人利用。

常见的操作是将显示RGBA阵列分成R,G,B和A平面。 使用预先计算的索引,如这些字节不变的偏移:

A = (0x03020100>>0x18)&0xff;
B = (0x03020100>>0x10)&0xff;
G = (0x03020100>>0x08)&0xff;
R = (0x03020100>>0x00)&0xff;

一个字节序的值为0,1,2,3,另一个的值为3,2,1,0。 许多编译器执行计算并将它们转换为清单常量。 不再需要依赖于顺序的位移来提取单个组件。 我把它留给读者重新命名,以适应他们选择的味道。

在C:

unsigned long source = 0x01234567, target = 0x0;
unsigned char src = (unsigned char *)&source;
unsigned char tgt = (unsigned char *)&target;
tgt[A] = src[R]; tgt[B] = src[G]; tgt[G] = src[B]; tgt[R] = src[A];

在Python,javascript,PHP和其他许多人中:

src = [0x01, 0x23, 0x45, 0x67]
tgt = [0,0,0,0]
tgt[A] = src[R]; tgt[B] = src[G]; tgt[G] = src[B]; tgt[R] = src[A];

享受(有时显着)性能提升, 使用我的朋友的清晰度。

如果有人感兴趣,我将提供卷积/相关性能提升技术。