我正在尝试编写一些独立于处理器的代码来编写大端的一些文件。我有一个下面的代码示例,我不明白为什么它不起作用。它应该做的就是让字节以大端顺序逐个存储数据的每个字节。在我的实际程序中,我会将单个字节写入文件,因此无论处理器架构如何,我都会在文件中获得相同的字节顺序。
#include <iostream>
int main (int argc, char * const argv[]) {
long data = 0x12345678;
long bitmask = (0xFF << (sizeof(long) - 1) * 8);
char byte = 0;
for(long i = 0; i < sizeof(long); i++) {
byte = data & bitmask;
data <<= 8;
}
return 0;
}
由于某些原因,byte始终具有值0.这让我感到困惑,我正在查看调试器并看到:
data = 00010010001101000101011001111000 bitmask = 11111111000000000000000000000000
我认为数据&amp;掩码会给00010010,但它每次只生成字节00000000!他怎么样?我已经为小端序写了一些代码,这很好用,见下文:
#include <iostream>
int main (int argc, char * const argv[]) {
long data = 0x12345678;
long bitmask = 0xFF;
char byte = 0;
for(long i = 0; i < sizeof(long); i++) {
byte = data & bitmask;
data >>= 8;
}
return 0;
}
为什么小端的工作和大端不工作?感谢您的帮助: - )
答案 0 :(得分:6)
您应该使用标准函数ntohl()
和亲属。它们使用显式大小的变量(即uint16_t
和uin32_t
),而不是特定于编译器的long
,这对于可移植性来说是必不可少的。
某些平台在<endian.h>
答案 1 :(得分:2)
你的转变是错误的。
#include <iostream>
int main (int argc, char * const argv[]) {
long data = 0x12345678;
int shift = (sizeof(long) - 1) * 8
const unsigned long mask = 0xff;
char byte = 0;
for (long i = 0; i < sizeof(long); i++, shift -= 8) {
byte = (data & (mask << shift)) >> shift;
}
return 0;
}
现在,我不建议你这样做。我建议改为编写一些很好的转换函数。许多编译器将这些作为内置函数。所以你可以编写你的函数来完成它,然后在你弄清楚它是什么时将它们切换到内置的编译器。
#include <tr1/cstdint> // To get uint16_t, uint32_t and so on.
inline uint16_t to_bigendian(uint16_t val, char bytes[2])
{
bytes[0] = (val >> 8) & 0xffu;
bytes[1] = val & 0xffu;
}
inline uint32_t to_bigendian(uint32_t val, char bytes[4])
{
bytes[0] = (val >> 24) & 0xffu;
bytes[1] = (val >> 16) & 0xffu;
bytes[2] = (val >> 8) & 0xffu;
bytes[3] = val & 0xffu;
}
此代码比循环更简单,更易于理解。它也更快。最后,它被一些编译器识别并自动转换为大多数CPU所需的单字节交换操作。
答案 2 :(得分:2)
在您的示例中,数据为0x12345678。
因此,您对字节的第一次分配是:
byte = 0x12000000;
不适合一个字节,因此会被截断为零。
尝试:
byte = (data & bitmask) >> (sizeof(long) - 1) * 8);
答案 3 :(得分:0)
因为你正在从一个整数中屏蔽掉顶部字节,然后再将其向下移回24位......
将您的循环更改为:
for(long i = 0; i < sizeof(long); i++) {
byte = (data & bitmask) >> 24;
data <<= 8;
}