如何双端独立存储

问题描述 投票:0回答:6

尽管大端计算机并未得到广泛使用,但我想以独立的格式存储双精度数据类型。

对于

int
(或任何整数类型),这非常简单,因为位移位使这非常方便。

int number;
int size=sizeof(number);
char bytes[size];

for (int i=0; i<size; ++i)
    bytes[size-1-i] = (number >> 8*i) & 0xFF;

此代码片段以大端格式存储数字,无论其运行在什么机器上。 对 double 执行此操作最优雅的方法是什么?

c++ c interop endianness
6个回答
7
投票
考虑到可移植性并考虑格式的最佳方法是分别序列化/反序列化尾数和指数。为此,您可以使用 frexp()/ldexp() 函数。

例如,序列化:

int exp; unsigned long long mant; mant = (unsigned long long)(ULLONG_MAX * frexp(number, &exp)); // then serialize exp and mant.

然后反序列化:

// deserialize to exp and mant. double result = ldexp ((double)mant / ULLONG_MAX, exp);
    

6
投票
优雅的做法是将字节序问题限制在尽可能小的范围内。这个狭窄的范围就是你的程序和外界之间的 I/O 边界。例如,向其他应用程序发送二进制数据或从其他应用程序接收二进制数据的函数需要注意字节序问题,向某些数据文件写入二进制数据或从某些数据文件读取二进制数据的函数也需要注意字节序问题。让这些界面认识到表示问题。

让其他一切都幸福地忽视这个问题。在其他地方使用当地代表。将双精度浮点数表示为

double

 而不是 8 字节数组,将 32 位整数表示为 
int
int32_t
 而不是 4 字节数组,等等。在整个代码中处理字节顺序问题将使您的代码变得臃肿、容易出错且丑陋。


1
投票
一样。任何数字对象(包括 double)最终都是几个字节,这些字节根据字节顺序以特定顺序进行解释。因此,如果您恢复字节顺序,您将在反转的字节顺序中获得完全相同的值。


1
投票
char *src_data; char *dst_data; for (i=0;i<N*sizeof(double);i++) *dst_data++=src_data[i ^ mask]; // where mask = 7, if native == low endian // mask = 0, if native = big_endian
优雅之处在于 

mask

,它还可以处理 
short
int
 类型:如果目标和源字节序不同,则为 
sizeof(elem)-1


0
投票
不太便携且违反标准,但类似这样:

std::array<unsigned char, 8> serialize_double( double const* d ) { std::array<unsigned char, 8> retval; char const* begin = reinterpret_cast<char const*>(d); char const* end = begin + sizeof(double); union { uint8 i8s[8]; uint16 i16s[4]; uint32 i32s[2]; uint64 i64s; } u; u.i64s = 0x0001020304050607ull; // one byte order // u.i64s = 0x0706050403020100ull; // the other byte order for (size_t index = 0; index < 8; ++index) { retval[ u.i8s[index] ] = begin[index]; } return retval; }

可以处理具有 8 位字符、8 字节双精度和任何疯狂的字节排序的平台(例如,单词中的大端序,但 64 位值的字之间的小端序)。

现在,这不包括双精度数与 64 位整数的字节序不同。

更简单的方法可能是将双精度型转换为 64 位无符号值,然后像输出任何其他 int 一样输出它。


0
投票
void reverse_endian(double number, char (&bytes)[sizeof(double)]) { const int size=sizeof(number); memcpy(bytes, &number, size); for (int i=0; i<size/2; ++i) std::swap(bytes[i], bytes[size-i-1]); }
    
© www.soinside.com 2019 - 2024. All rights reserved.