C ++中用于文件的Big Endian和Little Endian

时间:2010-01-29 10:57:40

标签: c++ file endianness

我正在尝试编写一些独立于处理器的代码来编写大端的一些文件。我有一个下面的代码示例,我不明白为什么它不起作用。它应该做的就是让字节以大端顺序逐个存储数据的每个字节。在我的实际程序中,我会将单个字节写入文件,因此无论处理器架构如何,我都会在文件中获得相同的字节顺序。

#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;
}

为什么小端的工作和大端不工作?感谢您的帮助: - )

4 个答案:

答案 0 :(得分:6)

您应该使用标准函数ntohl()和亲属。它们使用显式大小的变量(即uint16_tuin32_t),而不是特定于编译器的long,这对于可移植性来说是必不可少的。

某些平台在<endian.h>

中提供64位版本

答案 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;
    }