【问题标题】:GCC #define statement bytes wrong orderGCC #define 语句字节顺序错误
【发布时间】:2012-11-09 20:37:43
【问题描述】:

对于我正在进行的项目,我使用幻数。 这个宏用来定义一个

#define BOOTSIGNATURE 0xAA55

但是,当我对生成的文件进行 HEXDUMP 处理时,应该说 AA55 的地方却是 55 AA。

是 GCC 混淆了字节顺序,还是我?该项目适用于 x86 处理器。 AA 55 需要按特定顺序排列。我可以只交换字节,但我很好奇 GCC 为什么要这样做。

【问题讨论】:

  • 由于 x86 是小端,我可以理解为什么 GCC 认为这是想要的行为。但是,对我来说,AA55 有点像一串字节,需要按特定顺序。我怎样才能实现所需的行为?
  • 您可以将其定义为字节字符串(数组)而不是单个整数。我不知道你是如何使用它的,所以我不知道它是否可以在没有其他修改的情况下工作。 #define BOOTSIGNATURE ((char[]){0xAA,0x55})。您也可以只检查架构并切换顺序,留下评论以便您知道原因。
  • 二进制文件以与机器相同的字节顺序写入,当它再次加载时,它将被正确读取,如果你担心的话。
  • 不,这是一个神奇的数字,这不是一个解决方案。

标签: c gcc x86 c-preprocessor endianness


【解决方案1】:

0xAA55int,因此您受制于机器的字节序。我会将其存储为 char 数组:

const unsigned char BOOTSIGNATURE[] = {0xAA, 0x55};

【讨论】:

  • 太棒了。因此,如果我将其转换为 unsigned short int 它将作为结构的一部分工作?
  • 是的,您可以将其转换为无符号短整数。您如何处理文件的其余部分?也是小端吗?在这种情况下,这只是冰山一角。
  • 不,不是问题。文件的其余部分在 GCC 域中(由 GCC 样式编译的 c 代码编写和读取)引导签名(如名称所示;))由 BIOS 读取以验证我的磁盘映像的前 512 是否有效用于启动。这就是为什么字节的顺序在那里很重要,而不是其他地方。当另一个扇区被读取时,字节序影响被抵消,因为它是使用相同的字节序读取的。然而,BIOS 要求这些字节按特定顺序排列。
  • 哦,顺便说一句,我知道字节顺序是 x86 的一个特性,而不是 GCC,但只是说要指出在这种情况下阅读是“我无法控制的”,而不是在任何其他情况下案例。
【解决方案2】:

预处理器宏不会出现在编译的目标文件中——编译器根本看不到它们。如果您只是拥有那个#define 并且从未在任何地方使用过它,那么就不会留下任何痕迹。

如果您在某处的代码中使用它,它可能会在指令中显示为常量(例如,将常量加载到寄存器或内存中)。如果你用它来初始化静态数据,它会在数据段中显示为一个常量:

// Global variable definition
#define BOOTSIGNATURE 0xAA55
uint16_t my_global = BOOTSIGNATURE;

如果你编译上面的,看数据段,是这样的:

$ gcc -c test.c
$ objdump -s test.o
[...]
Contents of section .data:
 0000 55aa0000                             U...

如您所见,这两个字节以小端序55 AA 存储在内存中(前导0000 是十六进制的段偏移量)。

如果要控制数据的字节顺序,则将其存储为显式字节数组:

uint8_t my_global[] = {0xAA, 0x55};

这将始终按指定的顺序存储字节。

【讨论】:

  • 我当然知道这一点,显然我在某处使用过它。那么这个字节数组可以转换成一个短整型呢?
【解决方案3】:

如果您想编写可移植的代码,您可以使用函数来强制指定给定的字节顺序。例如,these functions 允许您将本机主机字节顺序中的 16 位值转换为大端或小端,具体取决于您在文件中需要的顺序。

#define BOOTSIGNATURE 0xAA55

struct bootheader {
   uint16_t    signature_be;
} header;

header.signature_be = htobe16( BOOTSIGNATURE);

我喜欢在非主机字节顺序的变量和结构元素上使用_le_be 后缀。

因为你需要大端,你可以使用arpa/inet.h 中的htons(),但我不是那种方法的忠实拥护者。我不认为这个名字像htobe16 那样清晰,而且你没有转换成小端字节序的函数。

【讨论】:

    【解决方案4】:

    最简单的解决方案:使用十六进制值的整数形式,因此相应的二进制将产生相同的幻数!在本例中为 43605

    【讨论】:

    • 我不确定这是否更好。那只是0x55AA。你仍然有同样的字节序问题。
    • 也没有意识到这一点。刚刚更新了值,现在我不需要在我的其余代码中进行任何更改。
    猜你喜欢
    • 1970-01-01
    • 2015-06-07
    • 1970-01-01
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多