C 如何正确地指向这段内存以将其视为我的结构?

C 如何正确地指向这段内存以将其视为我的结构?,c,C,我有以下代码。该文件包含位图图像,第一个字节为0x424d。我希望第一个printf打印BM,而不是它打印BM 另外,第二个printf打印10,我希望它是一个更大的数字,因为文件大于10字节 fp = fopen("input.bmp", "r"); bmp_header_p = malloc(sizeof(bmp_header_t)); rewind(fp); fread(bmp_header_p, sizeof(char), 14, fp); printf("magic number

我有以下代码。该文件包含位图图像,第一个字节为0x424d。我希望第一个printf打印BM,而不是它打印BM

另外,第二个printf打印10,我希望它是一个更大的数字,因为文件大于10字节

fp = fopen("input.bmp", "r");
bmp_header_p = malloc(sizeof(bmp_header_t));

rewind(fp);
fread(bmp_header_p, sizeof(char), 14, fp);

printf("magic number = %s\n", bmp_header_p->magic);
printf("file size = %" PRIu32 "\n", bmp_header_p->filesz);

typedef struct {
uint8_t magic[2];   /* the magic number used to identify the BMP file:
                     0x42 0x4D (Hex code points for B and M).
                     The following entries are possible:
                     BM - Windows 3.1x, 95, NT, ... etc
                     BA - OS/2 Bitmap Array
                     CI - OS/2 Color Icon
                     CP - OS/2 Color Pointer
                     IC - OS/2 Icon
                     PT - OS/2 Pointer. */
uint32_t filesz;    /* the size of the BMP file in bytes */
                     of the byte where the bitmap data can be found. */
} bmp_header_t;
%s表示以null结尾的字符串。magic只是一个2字节的数组,而不是一个字符串

printf("magic number = %c%c\n", bmp_header_p->magic[0], bmp_header_p->magic[1]);
%s表示以null结尾的字符串。magic只是一个2字节的数组,而不是一个字符串

printf("magic number = %c%c\n", bmp_header_p->magic[0], bmp_header_p->magic[1]);

当您将某个内容打印为字符串时,printf函数将一直运行,直到到达空终止符。因此,尽管前两个字节可能代表BM,但您没有采取任何措施确保打印停止在那里。除非内存中的下一个字节是“0”,否则printf将继续查找字符并打印它们。接下来的两个是不可打印的,结果是??。之后,可能会出现“0”,因此输出停止

至于第二点,格式规范说整数是以小端格式存储的。你没有做任何事情来确保你是这样解释这个数字的——有可能你实际上是在使用一台big-endian机器,在这种情况下,数字10实际上是10*256*256=167772160。当然,不能保证结构中的数字实际上是按照您的想法对齐的——有可能存在某些编译器、特定于平台的填充。还有一个问题,当二进制文件以r模式而不是rb模式打开时会发生什么

以下是解决这些问题的可能方法:

#define HEADER_SIZE 14
#define SIZE_START 2

fp = fopen("input.bmp", "r");
bmp_header_p = malloc(HEADER_SIZE);

fread(bmp_header_p, HEADER_SIZE, 1, fp);

printf("magic number = %c%c\n", bmp_header_p[0], bmp_header_p[1]);

long int fileSize=0, ii;
for(ii=0;ii<4;ii++) fileSize+=256*fileSize + bmp_header+p[ii + SIZE_START];

printf("file size = %ld\n", fileSize);

当您将某个内容打印为字符串时,printf函数将一直运行,直到到达空终止符。因此,尽管前两个字节可能代表BM,但您没有采取任何措施确保打印停止在那里。除非内存中的下一个字节是“0”,否则printf将继续查找字符并打印它们。接下来的两个是不可打印的,结果是??。之后,可能会出现“0”,因此输出停止

至于第二点,格式规范说整数是以小端格式存储的。你没有做任何事情来确保你是这样解释这个数字的——有可能你实际上是在使用一台big-endian机器,在这种情况下,数字10实际上是10*256*256=167772160。当然,不能保证结构中的数字实际上是按照您的想法对齐的——有可能存在某些编译器、特定于平台的填充。还有一个问题,当二进制文件以r模式而不是rb模式打开时会发生什么

以下是解决这些问题的可能方法:

#define HEADER_SIZE 14
#define SIZE_START 2

fp = fopen("input.bmp", "r");
bmp_header_p = malloc(HEADER_SIZE);

fread(bmp_header_p, HEADER_SIZE, 1, fp);

printf("magic number = %c%c\n", bmp_header_p[0], bmp_header_p[1]);

long int fileSize=0, ii;
for(ii=0;ii<4;ii++) fileSize+=256*fileSize + bmp_header+p[ii + SIZE_START];

printf("file size = %ld\n", fileSize);

您有几个问题:

编译器可能会在magic和filesz成员之间的数据结构中添加填充。有一些特定于编译器的扩展,例如pragmas和属性,可以用来避免这种行为并获得压缩结构。但这些都不是便携式的,如果可能的话应该避免。 %s格式说明符要求以null结尾的字符串,但您传递的字符串未终止。您应该改为使用说明符,如%.2s,以打印最多2个字符。 位图文件格式为little endian。如果您的计算机也是little endian,那么它似乎可以正常工作,但是当您为big endian体系结构编译时,您会发现它会突然停止工作。必须在big-endian平台上交换任何多字节值,如filesz。 无需调用rewind3。打开文件后,文件指针保证位于文件的开头。 解决问题1的方法有很多;关于如何在C中正确地进行序列化,有无数的文章和答案。我建议您单独阅读每个成员,这样您就不必担心编译器如何布局您的结构,并且它将完全可移植到所有平台


此外,sizeofchar在C标准中保证为1,因此几乎不需要在fread3的函数参数中显式写出sizeofchar。

您有几个问题:

编译器可能会在magic和filesz成员之间的数据结构中添加填充。有一些特定于编译器的扩展,例如pragmas和属性,可以用来避免这种行为并获得压缩结构。但这些都不是便携式的,如果可能的话应该避免。 %s格式说明符要求以null结尾的字符串,但您传递的字符串未终止。您应该改为使用说明符,如%.2s,以打印最多2个字符。 位图文件格式为little endian。如果您的计算机也是little endian,那么它似乎可以正常工作,但是当您为big endian体系结构编译时,您会发现它会突然停止工作。必须在big-endian平台上交换任何多字节值,如filesz rms。 无需调用rewind3。打开文件后,文件指针保证位于文件的开头。 解决问题1的方法有很多;关于如何在C中正确地进行序列化,有无数的文章和答案。我建议您单独阅读每个成员,这样您就不必担心编译器如何布局您的结构,并且它将完全可移植到所有平台


此外,sizeofchar在C标准中保证为1,因此几乎不需要在fread3的函数参数中显式写出sizeofchar。

只需填充一个以3个字符为空结尾的数组即可

字符标签[]=00\0; 标签[0]=魔术[0]; 标签[1]=魔术[1];
打印%s\n,标签

只需填充一个3字符的空终止数组

字符标签[]=00\0; 标签[0]=魔术[0]; 标签[1]=魔术[1];
打印%s\n,标签

%s转换需要指向以0结尾的字符数组的第一个元素的指针。您没有传递它。您需要以二进制模式打开文件。%s转换需要指向以0结尾的字符数组的第一个元素的指针。你一个都没有通过。你需要以二进制模式打开你的文件。我明白了。对filesz有什么想法吗?预期的filesz是什么?文件应该是BMP文件的大小。703K input.BMP结构对齐和大/小相关性是最有可能的罪魁祸首。因为现在大多数常见的处理器都是小端,所以我不认为endianness可能是罪魁祸首。但关于对齐,你可能是对的。我明白了。对filesz有什么想法吗?预期的filesz是什么?文件应该是BMP文件的大小。703K input.BMP结构对齐和大/小相关性是最有可能的罪魁祸首。因为现在大多数常见的处理器都是小端,所以我不认为endianness可能是罪魁祸首。但关于对齐,你可能是对的。