C++11:字节序转换
C++11: endian 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 检查它吗?
对于有符号整数,代码不起作用,但我不知道为什么。有人可以给我提示吗?
我知道如果主机字节序等于本地字节序,这段代码会很慢,但这对我的用例来说没有问题。
非常感谢
此致
凯文
易于识别和转换。
这是一个如此频繁的操作
如此频繁地通过检测循环和移位来完成
我觉得我应该提供方法
我已经使用了十多年
供其他人使用。
一个常见的操作是将一个显示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。
许多编译器执行计算并将这些转换为清单常量。
不再需要依赖顺序的位移位来提取单个组件。
我让 reader 重命名这些以适应他们选择的口味。
在 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];
享受(有时是显着的)性能提升,
和使用我的朋友的清晰度。
如果有人感兴趣,我会提供 convolution/correlation 性能提升技术。
我试图在编译时获取系统字节编码 (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 检查它吗?
对于有符号整数,代码不起作用,但我不知道为什么。有人可以给我提示吗?
我知道如果主机字节序等于本地字节序,这段代码会很慢,但这对我的用例来说没有问题。
非常感谢
此致
凯文
易于识别和转换。 这是一个如此频繁的操作 如此频繁地通过检测循环和移位来完成 我觉得我应该提供方法 我已经使用了十多年 供其他人使用。
一个常见的操作是将一个显示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。 许多编译器执行计算并将这些转换为清单常量。 不再需要依赖顺序的位移位来提取单个组件。 我让 reader 重命名这些以适应他们选择的口味。
在 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];
享受(有时是显着的)性能提升, 和使用我的朋友的清晰度。
如果有人感兴趣,我会提供 convolution/correlation 性能提升技术。