字节序是否影响写入奇数个字节?
Does endianness affect writing an odd number of bytes?
假设您有一个 uint64_t bytes
并且您知道您只需要 7 个字节,因为您存储的整数不会超过 7 个字节的限制。
写文件时你可以做类似的事情
std::ofstream fout(fileName);
fout.write((char *)&bytes, 7);
只写 7 个字节。
我想弄清楚的问题是系统的字节顺序是否会影响写入文件的字节数。我知道字节顺序会影响写入字节的顺序,但它是否也会影响写入哪些字节? (仅适用于您写入的字节数少于整数通常所具有的字节数的情况。)
例如,在小端系统上,前 7 个字节从 LSB 开始写入文件。在大端系统上写入文件的是什么?
或者换句话说,在小端系统上,MSB(第 8 个字节)不会写入文件。我们可以在大端系统上期待相同的行为吗?
字节序仅影响 (16, 32, 64) int
的书写方式。如果您正在编写 bytes,(根据您的情况)它们将按照您正在执行的完全相同的顺序编写。
比如这种写法会受到endianess的影响:
std::ofstream fout(fileName);
int i = 67;
fout.write((char *)&i, sizeof(int));
uint64_t bytes = ...;
fout.write((char *)&bytes, 7);
这将从 &bytes 的地址开始正好写入 7 个字节。 LE 和 BE 系统在内存中的八个字节的布局方式有所不同(假设变量位于地址 0xff00
):
0xff00 0xff01 0xff02 0xff03 0xff04 0xff05 0xff06 0xff07
LE: [byte 0 (LSB!)][byte 1][byte 2][byte 3][byte 4][byte 5][byte 6][byte 7 (MSB)]
BE: [byte 7 (MSB!)][byte 6][byte 5][byte 4][byte 3][byte 2][byte 1][byte 0 (LSB)]
起始地址 (0xff00
) 如果转换为 char* 则不会改变,并且您将打印出恰好位于该地址的字节加上接下来的六个字节 - 在这两种情况下(LE 和 BE ), 地址 0xff07
将不会被打印出来。现在如果你看看我上面的记忆table,很明显在BE系统上,你在存储不携带信息的MSB时丢失了LSB...
在 BE 系统上,您可以改写 fout.write((char *)&bytes + 1, 7);
。但是请注意,这仍然存在可移植性问题:
fout.write((char *)&bytes + isBE(), 7);
// ^ giving true/false, i. e. 1 or 0
// (such function/test existing is an assumption!)
这样,BE 系统写入的数据在回读时会被 LE 系统误解,反之亦然。安全版本会将每个字节分解为 geza did in his 。为避免多次系统调用,您可以将值分解为一个数组并打印出该数组。
如果在 linux/BSD 上,还有一个不错的 alternative:
bytes = htole64(bytes); // will likely result in a no-op on LE system...
fout.write((char *)&bytes, 7);
The question I'm trying to figure out is whether endianess of a system affects the bytes that are written to the file.
是的,它会影响写入文件的字节数。
For example, on a little endian system the first 7 bytes are written to the file, starting with the LSB. On a big endian system what is written to the file?
前 7 个字节已写入文件。但这一次,从 MSB 开始。所以,最后,最低字节是不写入文件,因为在big endian系统上,最后一个字节是最低字节。
所以,这不是您想要的,因为您丢失了信息。
一个简单的解决方案是将uint64_t
转换为little endian,并将转换后的值写入。或者只是以小端系统写入的方式逐字节写入值:
uint64_t x = ...;
write_byte(uint8_t(x));
write_byte(uint8_t(x>>8));
write_byte(uint8_t(x>>16));
// you get the idea how to write the remaining bytes
假设您有一个 uint64_t bytes
并且您知道您只需要 7 个字节,因为您存储的整数不会超过 7 个字节的限制。
写文件时你可以做类似的事情
std::ofstream fout(fileName);
fout.write((char *)&bytes, 7);
只写 7 个字节。
我想弄清楚的问题是系统的字节顺序是否会影响写入文件的字节数。我知道字节顺序会影响写入字节的顺序,但它是否也会影响写入哪些字节? (仅适用于您写入的字节数少于整数通常所具有的字节数的情况。)
例如,在小端系统上,前 7 个字节从 LSB 开始写入文件。在大端系统上写入文件的是什么?
或者换句话说,在小端系统上,MSB(第 8 个字节)不会写入文件。我们可以在大端系统上期待相同的行为吗?
字节序仅影响 (16, 32, 64) int
的书写方式。如果您正在编写 bytes,(根据您的情况)它们将按照您正在执行的完全相同的顺序编写。
比如这种写法会受到endianess的影响:
std::ofstream fout(fileName);
int i = 67;
fout.write((char *)&i, sizeof(int));
uint64_t bytes = ...;
fout.write((char *)&bytes, 7);
这将从 &bytes 的地址开始正好写入 7 个字节。 LE 和 BE 系统在内存中的八个字节的布局方式有所不同(假设变量位于地址 0xff00
):
0xff00 0xff01 0xff02 0xff03 0xff04 0xff05 0xff06 0xff07
LE: [byte 0 (LSB!)][byte 1][byte 2][byte 3][byte 4][byte 5][byte 6][byte 7 (MSB)]
BE: [byte 7 (MSB!)][byte 6][byte 5][byte 4][byte 3][byte 2][byte 1][byte 0 (LSB)]
起始地址 (0xff00
) 如果转换为 char* 则不会改变,并且您将打印出恰好位于该地址的字节加上接下来的六个字节 - 在这两种情况下(LE 和 BE ), 地址 0xff07
将不会被打印出来。现在如果你看看我上面的记忆table,很明显在BE系统上,你在存储不携带信息的MSB时丢失了LSB...
在 BE 系统上,您可以改写 fout.write((char *)&bytes + 1, 7);
。但是请注意,这仍然存在可移植性问题:
fout.write((char *)&bytes + isBE(), 7);
// ^ giving true/false, i. e. 1 or 0
// (such function/test existing is an assumption!)
这样,BE 系统写入的数据在回读时会被 LE 系统误解,反之亦然。安全版本会将每个字节分解为 geza did in his
如果在 linux/BSD 上,还有一个不错的 alternative:
bytes = htole64(bytes); // will likely result in a no-op on LE system...
fout.write((char *)&bytes, 7);
The question I'm trying to figure out is whether endianess of a system affects the bytes that are written to the file.
是的,它会影响写入文件的字节数。
For example, on a little endian system the first 7 bytes are written to the file, starting with the LSB. On a big endian system what is written to the file?
前 7 个字节已写入文件。但这一次,从 MSB 开始。所以,最后,最低字节是不写入文件,因为在big endian系统上,最后一个字节是最低字节。
所以,这不是您想要的,因为您丢失了信息。
一个简单的解决方案是将uint64_t
转换为little endian,并将转换后的值写入。或者只是以小端系统写入的方式逐字节写入值:
uint64_t x = ...;
write_byte(uint8_t(x));
write_byte(uint8_t(x>>8));
write_byte(uint8_t(x>>16));
// you get the idea how to write the remaining bytes