我正在涉猎一点Game Boy save state黑客攻击,目前我正在研究如何读取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 %i\n", errno); 
   fseek(fp, 0L, SEEK_END); //seek to end to get file size
   filesize = ftell(fp);
   printf("Filesize is %i bytes\n",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("%x\n", 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 %i\n", 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("%x\n", buffer[i]);

要打印unsigned char,请使用%hhx.因为你的buffer已经签署了char个元素,其中一些是负数.在这printf中使用时,它们被提升为负值int.然后,由于%xprintftry 将它们打印为unsigned int个值.两个补码形式的负值中的所有额外位都显示出来了.

C++相关问答推荐

MISIX标准和信号量的语义

在x86汇编中,为什么当分子来自RDRAND时DIV会引发异常?

如何通过Zephyr(Devicetree)在PR Pico上设置UTE 1?

C中空终止符后面的数字?

字符串令牌化xpath表达式

DPDK-DumpCap不捕获端口上的传入数据包

我编译了一个新的c程序,并收到以下错误

使用GOTO从多个嵌套循环C继续

如何跨平台处理UTF-16字符串?

C由四个8位整数组成无符号32位整数

以下声明和定义之间的区别

为什么我会收到释放后堆使用错误?

无法在OpenGL上绘制三角形

如何用c语言修改shadow文件hash部分(编程)?

I2C外设在单次交易后出现故障

我在C程序的Flex/Bison中遇到语法错误

带有数组指针的 struct 在print_stack()函数中打印随机数

使用 _Atomic float 时,MSVC 编译的代码会命中调试断言

为什么写入关闭管道会返回成功

获取 struct 中匿名 struct 的大小