GCC #define语句字节错误的顺序

时间:2012-11-09 20:37:43

标签: c gcc x86 c-preprocessor endianness

对于我正在研究的项目,我使用魔术数字。 该宏用于定义一个

#define BOOTSIGNATURE 0xAA55

然而,当我HEXDUMP生成的文件时,它应该说AA55它说55 AA。

海湾合作委员会是否会混淆字数,或者是我?该项目适用于x86处理器。 AA 55需要按特定顺序排列。我可以只交换字节,但我很好奇为什么GCC这样做。

4 个答案:

答案 0 :(得分:2)

0xAA55int,因此您需要遵守机器的字节顺序。我将它存储为char数组:

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

答案 1 :(得分: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};

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

答案 2 :(得分:0)

如果要编写可移植代码,则可以使用函数强制执行给定的字节顺序。例如,these functions允许您将本机host-byte-order中的16位值转换为big-endian或little-endian,具体取决于文件中所需的顺序。

#define BOOTSIGNATURE 0xAA55

struct bootheader {
   uint16_t    signature_be;
} header;

header.signature_be = htobe16( BOOTSIGNATURE);

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

由于你需要big-endian,你可以使用htons()中的arpa/inet.h,但我不是那种方法的忠实粉丝。我不认为名称与htobe16一样清晰,并且您没有转换为/从little-endian字节顺序转换的函数。

答案 3 :(得分:-2)

最简单的sollution:使用十六进制值的整数形式,因此相应的二进制将产生相同的幻数!在这种情况下,这将是43605