要完全确定,我想知道以下C ++代码是否安全,特别是endian安全吗?我希望这个程序能够从二进制文件中的任何计算机上写入,然后从任何其他计算机(可能具有另一个字节顺序)读取该文件(即可移植)。
#include <iostream>
#include <fstream>
using namespace std;
#define BUFF_SIZE 64
template <typename type> void toBin(type value, char * buffer, size_t size);
template <typename type> type toDec(char * buffer, size_t size);
int main()
{
long long x = 238920134300912;
char * buffer = (char*)calloc(BUFF_SIZE, sizeof(char));
// Write x
toBin<long long>(x, buffer, BUFF_SIZE);
ofstream outFile("test.bin", ios::out | ios::binary);
outFile.write(buffer, BUFF_SIZE);
outFile.close();
// -------------------------------------------------------------------------
// Read x (from another computer...)
ifstream inFile("test.bin", ios::in | ios::binary);
inFile.read(buffer, BUFF_SIZE);
cout << toDec<long long>(buffer, BUFF_SIZE) << endl;
inFile.close();
// Free the buffer.
free(buffer);
return 0;
}
template <typename type> void toBin(type value, char * buffer, size_t size)
{
if (sizeof(type) > size)
throw new invalid_argument("Buffer too small");
for (size_t i = 0; i < sizeof(type); i++)
buffer[i] = (value >> i * 8) & 0xff;
}
template <typename type> type toDec(char * buffer, size_t size)
{
if (sizeof(type) > size)
throw new invalid_argument("Buffer too small");
type value = 0;
for (size_t i = 0; i < sizeof(type); i++)
value += ((type)buffer[i] & 0xff) << (8 * i);
return value;
}
答案 0 :(得分:2)
除了一件事,我看起来不错。我会将8
替换为CHAR_BIT
而将0xff
替换为UCHAR_MAX
。
buffer[i] = (value >> (i * CHAR_BIT)) & UCHAR_MAX;
和
value += ((type)buffer[i] & UCHAR_MAX) << (CHAR_BIT * i);
答案 1 :(得分:1)
你应该看一下htons()
family of functions。它们是库函数,它们将主机的字节序转换为&#34;网络字节顺序&#34;即大端。这些功能保证是可移植的,并且可能比您自己的实现更快。
如果你想确保可移植性,你还应该在几个平台上测试代码,以确保它实际工作。在大型程序中,您很可能忘记在某处转换字节序。该程序仍然可以在原始平台上运行,因此您需要在另一个平台上进行测试以检测错误。
答案 2 :(得分:0)
是的,你可以这样做,但速度很慢。
或者,只需用数据(以便携方式)写入一个标志,指示文件中数据的字节顺序(您的写程序甚至可以采用一个布尔参数来指示它应该写入哪个字节序,默认为当前硬件的值)。然后,读取代码可以检测字节顺序是否合规,如果需要,可以将字节翻转到位。
在编写器和阅读器具有相同字节序的可能情况下,这仅为普通I / O增加了很小的开销。 AFAIK,这是通常实现便携式二进制格式的方式(例如HDF5)。