文章

滴水-day20-宏定义-内存分配

宏定义

define 标识符1 标识符2

给一个标识符起一个新的名字,在编译前会把标识符1替换为标识符2.

\#deinfe 0

在程序中写FALSE后,在编译前会把FALSE替换为0;

/*if (DEBUG == 1)
	{
		printf("%d", ftellResult);
	}*/

这种简单的判断可以使用宏定义完成

#define PRINTFLOG(DE,RE) if ((DE) == 1){ printf("%d\\\\n",RE);}

PRINTFLOG为宏名称,他接受两个参数DE和RE,如果DE的值==1就打印RE的值,否则什么也不做。

头一次写宏定义,宏定义太高级了,简直和函数一样。

内存分配,文件读写

使用malloc进行内存分配

当读取文件的时候,不知道文件有多大,无法使用一个确定的指针来保存fopen返回的指针,这个时候就需要使用内存分配了。

void *malloc(
   size_t size
);

使用malloc最好使用类型转换转为需要的指针类型,size是需要分配多大的空间,以字节为单位。

errno_t fopen_s(
   FILE** pFile,
   const char *filename,
   const char *mode
);

使用fopen打开文件

pFile指向文件指针的指针,说白了就是二级指针,保存文件指针。

mode

要以什么样的方式打开这个文件,这个选项有很多

简单的:"r"表示读取。

errno_t就是int类型,返回0表示打开成功,可以进行下一步操作了。pFile已经保存文件的指针了。

size_t fread_s(
   void *buffer,
   size_t bufferSize,
   size_t elementSize,
   size_t count,
   FILE *stream
);

fread读取文件,返回读取到的项数,如果读取到的项数和count一致,代表读取成功。buffer是指针,指向读取后数据的指针。_bufferSize__count_设置为文件的大小就可以。elementSize表示一次都多少,以字节为单位。

int fseek(
   FILE *stream,
   long offset,
   int origin
);

long ftell(
   FILE *stream
);

SEEK_CUR:文件指针的当前位置。 SEEK_END:文件结尾。 SEEK_SET:文件开头。

使用fseek和ftell获取到文件的大小

fseek是移动指针到某个位置,可以使得指针移动到文件尾,在使用ftell获取当前指针的位置,这样就算是获取到文件的大小了。

再把指针移动到文件头,以免后续操作出现问题。

    fseek(notepad,0, SEEK_END);
	long ftellResult =  ftell(notepad);
	// 打印出ftellResult的结果
	PRINTFLOG(DEBUG, ftellResult);
	// 设置notepad指针指向文件头,当通过ftell获取到文件大小后再把notepad指针指向文件头,不然后面的读取会出错。
	fseek(notepad, 0, SEEK_SET);

练习

打开文件,读取数据,写入数据到另一个程序。

#include<iostream>
#include<stdio.h>
#include<Windows.h>

#define DEBUG 1
//#define notepadPath "C:\\\\\\\\Windows\\\\\\\\system32\\\\\\\\notepad.exe"
#define notepadPath "C:\\\\\\\\Users\\\\\\\\GaGa\\\\\\\\Desktop\\\\\\\\eee.exe"

#define PRINTFLOG(DE,dest) if ((DE) == 1){ printf("%x\\\\n",(dest));}
#define FALSE 0;

//constexpr auto notepadPath = "C:\\\\\\\\Windows\\\\\\\\system32\\\\\\\\notepad.exe";

/*
	errno_t fopen_s(
		FILE** pFile,
		const char *filename,
		const char *mode
);
*/
int main()
{
	// notepad保存的数据是指向文件指针的指针
	// 说白了就是二级指针

	FILE* notepad = NULL;

	// 打开文件
	errno_t err = fopen_s(&notepad, notepadPath, "rb");

	if (err == 0) {
		printf("notepda保存的数据:%p\\\\n", notepad);
	}
	else {
		printf("Failed to open file: %s\\\\n", notepadPath);
	}

	// 设置notepad指针指向文件尾
	fseek(notepad,0, SEEK_END);
	long ftellResult =  ftell(notepad);

	// 打印出ftellResult的结果
	PRINTFLOG(DEBUG, ftellResult);

	// 设置notepad指针指向文件头,当通过ftell获取到文件大小后再把notepad指针指向文件头,不然后面的读取会出错。
	fseek(notepad, 0, SEEK_SET);

	/*if (DEBUG == 1)
	{
		printf("%d", ftellResult);
	}*/

	// 分配内存空间
	unsigned char* notepadSpace = (unsigned char*)malloc(ftellResult);
	if (notepadSpace == NULL)
	{
		printf("Space Error");
		free(notepad);
		return FALSE;
	}

	// 读取内容,fread_s返回读取到的字节数,如果返回值不等于ftellResult,那么表示读取错误或读取失败
	size_t readNotepad = fread_s(notepadSpace, ftellResult, 1, ftellResult,notepad);
	if (readNotepad != ftellResult)
	{
		printf("read notepad.exe error\\\\n");
		return FALSE;
	}

	// 关闭文件
	fclose(notepad);

	// 打印地址
	printf("Addres---->%p\\\\n", notepadSpace);

	unsigned char* temp = notepadSpace; // 使用一个临时指针来遍历
	int count = 0;

	for (int i = 0; i < 200; i++)
	{
		printf("%-4x ", *(temp++));
		count++;
		if (count == 16)
		{
			printf("\\\\n");
			count = 0;
		}
	}

	printf("\\\\n--------------------\\\\n");
	// 释放内存
	//free(notepadSpace);

	// 打开目标文件
	FILE* dest = NULL;
	errno_t destExe = fopen_s(&dest, "test1.exe", "wb");
	// 写入目标文件
	size_t destNumber = fwrite(notepadSpace, 1, ftellResult, dest);
	printf("%x\\\\n", destNumber);
	fclose(dest);
	free(notepadSpace);

	return 0;
}

day20.cpp

day20.xlsx

InstDrv-PE解析.txt

License:  CC BY 4.0