滴水-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(¬epad, 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;
}
License:
CC BY 4.0