4

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

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

由于某种原因,字节的值始终为 0。这让我感到困惑,我正在查看调试器并看到以下内容:

数据 = 00010010001101000101011001111000 位掩码 = 11111111000000000000000000000000

我认为数据和掩码会给出 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

4 回答 4

6

您应该为此使用标准函数ntohl()和亲属。它们对显式大小的变量(即uint16_tuin32_t)进行操作,而不是long针对可移植性所必需的编译器特定的变量。

一些平台提供 64 位版本<endian.h>

于 2010-01-29T11:10:31.327 回答
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 所需的单字节交换操作。

于 2010-01-29T11:02:02.820 回答
2

在您的示例中,数据为 0x12345678。

因此,您对 byte 的第一个分配是:

byte = 0x12000000;

它不适合一个字节,所以它被截断为零。

尝试:

byte = (data & bitmask) >> (sizeof(long) - 1) * 8);
于 2010-01-29T11:02:10.997 回答
0

因为您要从整数中屏蔽最高字节,然后不将其向下移回 24 位...

将循环更改为:

for(long i = 0; i < sizeof(long); i++) {
        byte = (data & bitmask) >> 24;
        data <<= 8;
    }
于 2010-01-29T11:02:23.640 回答