首页 文章

C端文件的Big Endian和Little Endian

提问于
浏览
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;
}

由于某种原因,byte始终具有值0.这让我感到困惑,我正在查看调试器并看到:

data = 00010010001101000101011001111000 bitmask = 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 回答

  • 0

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

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

    byte = 0x12000000;
    

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

    尝试:

    byte = (data & bitmask) >> (sizeof(long) - 1) * 8);
    
  • 6

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

    某些平台在 <endian.h> 中提供64位版本

  • 1

    你的转变是错误的 .

    #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

    因为你从一个整数中屏蔽了顶部字节,然后没有将它向后移动24位......

    将你的循环改为:

    for(long i = 0; i < sizeof(long); i++) {
            byte = (data & bitmask) >> 24;
            data <<= 8;
        }
    

相关问题