如何从二进制文件获取十六进制转储到c



我正在涉足Game Boy保存状态黑客,我目前正在从c二进制文件中读取我的头。我知道char是一个字节,所以我正在使用以下代码读取字符

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main () {
FILE *fp = NULL;
char buffer[100];
int filesize;
fp = fopen("save file.srm", "r+"); //open
if(fp == NULL) printf("File loading error number %in", errno); 
fseek(fp, 0L, SEEK_END); //seek to end to get file size
filesize = ftell(fp);
printf("Filesize is %i bytesn",filesize);

fseek(fp, 0, SEEK_SET); //set read point at start of file
fread(buffer, sizeof buffer, 1, fp);//read into buffer

for(int i=70;i<80;i++) printf("%xn", buffer[i]); //display

fclose(fp);

return(0);
}
我得到的输出是
Filesize is 32768 bytes
ffffff89
66
ffffff85
2
2
ffffff8b
44
ffffff83
c
0

我试图以字节加载,所以我希望输出的每一行都具有最大值0xff。有人能解释一下为什么我得到ffffff8b吗?

if(fp == NULL) printf("File loading error number %in", errno);

当您检测到错误时,不要只是打印一条消息。要么退出程序,要么做一些事情来纠正错误。

char buffer[10];

使用unsigned char处理原始数据。char可能被签名,这可能会导致不希望的效果。

fread(buffer, strlen(buffer)+1, 1, fp);

此时buffer还没有初始化,所以strlen(buffer)的行为还没有被C标准定义。在任何情况下,您都不希望使用buffer中当前字符串的长度作为fread的大小。你想知道数组的大小。所以使用sizeof buffer(不使用+1)。

for(int i=0;i<10;i++)

不要迭代到10。迭代fread放入缓冲区的字节数。fread返回size_t值,即读取的项数。如果您将其用作size_t n = fread(buffer, 1, sizeof buffer, fp);,则项目的数量(在n中)将是读取的字节数,因为第二个参数为1表示要读取的每个项目是一个字节。

printf("%xn", buffer[i]);

打印unsigned char,使用%hhx。因为你的bufferchar元素有符号,所以有些元素是负的。当在printf中使用时,它们被提升为负int值。然后,由于%x,printf试图将它们打印为unsigned int值。在2的补码形式中,所有来自负值的额外位都显示出来。

非常简单:char可以默认为signedunsigned:这取决于编译器。在您的情况下,它似乎是signed.

当你将buffer[i]char传递给printf()时,它被提升为int,如果原来的char值已经设置了它的顶位,那么它的符号扩展。因此,在0x80-0xff范围内的任何内容都会获得大量的f前缀值。

如果将buffer声明为unsigned char,则不应出现此问题。但是,您应该结合printf()格式使用"%hhx"而不是"%x",因为hh长度修饰符强制printf()屏蔽输入值,以便仅使用适用于unsigned char的那些位(假设您正在使用x说明符)。

最新更新