我试图在编译时获得系统字节编码(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,这段代码很慢,但这对我的用例来说没问题。
非常感谢
祝你好运
凯文
答案 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 *)⌖
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];
享受(有时显着)性能提升, 使用我的朋友的清晰度。
如果有人感兴趣,我将提供卷积/相关性能提升技术。