0

在 Windows 中,您可以在尝试解析 bmp 文件时包含 windows.h 头文件,并且为您预定义了数据类型 WORD 和 DWORD(根据我所阅读的内容)。在 linux 中,我需要使用这些 dataTypes,但我不知道如何定义它们并且不能包含 windows.h 标头。我该如何在 C++ 中执行此操作?

4

1 回答 1

4

包括<stdint.h>,然后您可以WORDuint16_tDWORD替换uint32_t。当然BYTEuint8_t还有:

如果需要,可以添加以下代码:

#include <stdint.h>
typedef uint32_t DWORD;
typedef uint16_t WORD;
typedef uint8_t BYTE;

但要小心!如果您想要可移植,您必须牢记多字节值的字节顺序。Microsoft 代码几乎总是假定小端,但 Linux 可以在小端和大端机器上运行。

更新

您在评论中谈到的新问题BITMAPFILEHEADER与字段的类型无关,而是与结构的打包有关:编译器可能会在结构中的字段之间添加填充字节以满足对齐(或其他要求)。

Microsoft 编译器将整数类型与其大小的地址倍数对齐。也就是说,WORDandSHORT值与 2 的地址倍数对齐,DWORDandLONG值与 4 的倍数对齐。

如果您看到结构的定义:

typedef struct {
    WORD    bfType;      //offset 0
    DWORD   bfSize;      //offset 4
    WORD    bfReserved1; //offset 8
    WORD    bfReserved2; //offset 10
    DWORD   bfOffBits;   //offset 12
} BITMAPFILEHEADER;

请注意,该bfSize字段的大小为 4 个字节,因此它将对齐为 4 的倍数。而不是在结构的偏移量 2 中,它将在偏移量 4 中,添加 2 个填充字节。

现在,所有 Windows 头文件都使用#pragma pack告诉编译器忽略结构字段中的对齐限制的选项进行编译。所以前一个结构实际上是:

#pragma pack(push)
typedef struct {
    WORD    bfType;      //offset 0
    DWORD   bfSize;      //offset 2
    WORD    bfReserved1; //offset 6
    WORD    bfReserved2; //offset 8
    DWORD   bfOffBits;   //offset 10
} BITMAPFILEHEADER;
#pragma pack(pop)

GCC 编译器#pragma pack仅支持与 MS 编译器的兼容性,并且仅与 x86 编译器兼容。

如果你想完全可移植,你应该直接读取结构,但是将字节作为流读取并一个一个地构建值(将 2 个字节bfType读入 ,将 4 个字节读入bfSize,等等)

如果你想移植到其他 Linux,你可以使用 GCC pragma(但要注意字节序):

typedef struct __attribute__((packed)) {
    WORD    bfType;      //offset 0
    DWORD   bfSize;      //offset 2
    WORD    bfReserved1; //offset 6
    WORD    bfReserved2; //offset 8
    DWORD   bfOffBits;   //offset 10
} BITMAPFILEHEADER;
于 2012-09-08T21:42:19.627 回答