内存分配-文件读写

宏定义#define

1.宏定义说明:

一、无参数的宏定义的一般形式为:# define 标识符 字符序列

C程序->替换(预编译时)->编译->链接->硬编码(0x21)

宏定义 就是做替换(在预编译时) 如:

#define TRUE 1        
#define FALSE 0        
        
int fun()        
{        
    return TRUE;    
}        
        
#define PI 3.1415926                
            
double Function(int r)        
{        
    return 2*PI*r;    
}
​
#define DEBUG 1        
            
void Function()        
{        
        //....    
    if(DEBUG)    
        printf("测试信息");
}

注意事项:

1.只作字符序列的替换工作,不作任何语法的检查 2.如果宏定义不当,错误要到预处理之后的编译阶段才能发现

测试验证代码

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
​
#define TRUE 998    
#define FALSE 668    
#define PI 3.1415926
#define DEBUG 1
        
int fun1()        
{        
    return TRUE;
}
​
double fun2(int r)        
{        
    return 2*PI*r;    
}
​
void fun3()        
{        
    //....    
    if(DEBUG)    
        printf("Testing information\n");
}
​
int main(int argc, char* argv[])
{
    int x = fun1();
    printf("%d \n",x);
    float y = fun2(2);
    printf("%f \n",y);
    fun3();
    return 0;
}        
                      
      
                            

二、带参数宏定义:#define 标识符(参数表)字符序列

#define MAX(A,B) ((A) > (B)?(A):(B)) 
         

代码 x= MAX(p,q)将被替换成 y=((p) >(q)?(p):(q)

注意事项:

1.宏名标识符与左圆括号之间不允许有空白符,应紧接在一起.

2.宏与函数的区别:函数分配额外的堆栈空间,而宏只是替换.

3.为了避免出错,宏定义中给形参加上括号.

4.末尾不需要分号.

5.define可以替代多行的代码,记得后面加 \

#define MALLOC(n,type)\                        
            ((type*)malloc((n)*sizeof(type)))    

验证测试代码

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
​
#define MAX(A,B) ((A) > (B)?(A):(B)) // 这个的功能就是比较大小,谁大输出谁
​
int fun()        
{
    return MAX(9,18);
}
​
int main(int argc, char* argv[])
{
    int x = fun();
    printf("%d \n",x);
    return 0;
}

头文件的使用

测试

步骤一:                
                    

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
​
void fun( )
{
    printf("Hello World!\n");
}
​
​
int main(int argc, char* argv[])
{
    fun();
    return 0;
}
                    
可以正常执行                
                    
如果换成:                
                    
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
​
int main(int argc, char* argv[])
{
    fun();
    return 0;
}
​
void fun( )
{
    printf("Hello World!\n");
}                
                
不能正常执行!                
​
error C2065: 'fun' : undeclared identifier
error C2373: 'fun' : redefinition; different type modifiers

显示无法识别定义的函数,所以为了解决这类问题,就有了下面的办法 解决办法:新增头文件(.h),在.h文件中对函数进行说明

具体在VC6++上操作:在classes上右键新建,写一个名字x和y的两个文件,此时会在File栏目生成.cpp和.h的文件 (如果是C语言就是生成.c 如果C++那么就是生成.cpp) .cpp文件在Source Files .h文件在Header Files

                    
x.cpp文件的文件内容如下:
​

// x.cpp: implementation of the x class.
//
#include "stdafx.h"
#include "x.h"
​
​
// Construction/Destruction
//
​
void funx()
{
    printf("Hello x\n");
}
​
x.h文件的文件内容如下
​

// x.h: interface for the x class.
//
//
​
#if !defined(AFX_X_H__E1420025_F5C1_4883_8C12_957B2D2EEFD3__INCLUDED_)
#define AFX_X_H__E1420025_F5C1_4883_8C12_957B2D2EEFD3__INCLUDED_
​
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
​
void funx();
​
​
#endif // !defined(AFX_X_H__E1420025_F5C1_4883_8C12_957B2D2EEFD3__INCLUDED_)


​
y.cpp文件的文件内容如下:
​

// y.cpp: implementation of the y class.
//
​
#include "stdafx.h"
#include "y.h"
​
// Construction/Destruction
//
    
void funy()
{
    printf("Hello y\n");
}
​
​
​
y.h文件的文件内容如下
​
// y.h: interface for the y class.
//
//
​
#if !defined(AFX_Y_H__0CCFD82D_D027_419E_810C_22E1F91EA018__INCLUDED_)
#define AFX_Y_H__0CCFD82D_D027_419E_810C_22E1F91EA018__INCLUDED_
​
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
​
void funy();
​
​
#endif // !defined(AFX_Y_H__0CCFD82D_D027_419E_810C_22E1F91EA018__INCLUDED_)

下面是在上面的基础上,在主main函数下加载函数名称并执行,下面是主文件的源代码

// sjlx.cpp : Defines the entry point for the console application.
//
​
#include "stdafx.h"
#include "x.h"
#include "y.h"
​
​
int main(int argc, char* argv[])
{
    funx();
    funy();
    return 0;
}
​
上述可以编译成功并执行,打印结果如下:
Hello x
Hello y
Press any key to continue

重复包含的问题

内存分配与释放


malloc函数的使用和解释可参考下面链接 malloc 函数详解_wang13342322203的博客-CSDN博客_malloc

malloc函数使用流程

malloc函数使用流程
​
//声明指针
int* ptr;                 
                
//在堆中申请内存,分配128个int                
ptr = (int *)malloc(sizeof(int)*128);                
                
//无论申请的空间大小,一定要进行校验判断是否申请成功                
if(ptr == NULL)                
{                
    return 0;            
}
                
//初始化分配的内存空间                
memset(ptr,0,sizeof(int)*128);                
                
//开始使用        
*(ptr) = 1;                
                
//使用完毕 释放申请的堆空间                
free(ptr);                
                
//将指针设置为NULL                
ptr = NULL;

事例

#include "stdafx.h"
#include <malloc.h>
#include <memory.h>
​
int fun()
{
    //什么指针
    int* ptr;
    //在堆中申请内存,分配128个int
    ptr = (int*)malloc(sizeof(int)*128);
    //无论申请空间的大小,一定要先进行判断内存申请是否成功
    if (ptr == NULL)
    {
        return 0;
    }
    //初始化分配的内存空间
    memset(ptr,0,sizeof(int*)128);
    //开始使用内存
    *(ptr) = 1;
    //使用完内存,要释放申请的堆空间
    free(ptr);
    //将指针设置为NULL
    ptr = NULL;
​
    printf("%x \n",ptr);
}
​
int main(int argc, char* argv[])
{
    fun();
    printf("Hello World!\n");
    return 0;
}

文件读写相关函数(文件头stdio.h)

可以参考下面网站: 菜鸟教程 - 学的不仅是技术,更是梦想!

(1)fopen函数 打开文件函数 (打开一个文件并返回文件指针)

参考网站C函数篇(fopen函数) - sky of chuanqingchen - 博客园 (2)fseek函数 查找文件头或者尾函数(移动文件的读写指针到指定的位置)

相关参考: C 库函数 – fseek() | 菜鸟教程

(3)ftell函数 定位指针函数 (获取文件读写指针的当前位置)

相关参考: http://c.biancheng.net/cpp/html/2519.html

(4)fclose函数 关闭文件函数 (关闭文件流)

相关参考: http://c.biancheng.net/cpp/html/2505.html

(5)fread函数 读取文件内容函数 (从文件流中读取数据)

相关参考: http://c.biancheng.net/cpp/html/2516.html

测试的例子

#include "stdafx.h"
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
​
#define F_PATH "C:\\cntflx\\notepad.exe"
​
void pe_openfiles()
{
    FILE* fstream;
    fstream = fopen(F_PATH,"ab+");
​
    if (fstream == NULL)
    {
        printf("Open the notepad failed\n");
        exit(1);
    }
    else
    {
        printf("Open the notepad success!\n");
        printf("%x \n",fstream);
    }
​
    fclose(fstream);
​
    //return 0;
}

C语言获取文件大小 C语言获取文件大小_yutianzuijin的博客-CSDN博客_c语言判断文件大小

int pe_getfile_size()
{
    FILE* fp=fopen(F_PATH,"r");
    if (!fp)
    {
        return -1;
    }
    fseek(fp,0L,SEEK_END);
    int size = ftell(fp);
    fseek(fp,0,SEEK_SET);
    fclose(fp);
    
    return size;
}

课后练习

1.用十六进制文本编辑器,打开一个记事本的.exe文件,再打开在内存中的记事本进程,记录下这两个文件的不同.

操作方式: (1)使用winhex打开在硬盘上没有执行的notepad.exe文件,此时是没被执行的普通文件内容 (2)正常执行notepad.exe文件,然后最小化,再使用winhex的工具选项-打开RAM内存--选择名称为notepad.exe的内容

有两处不同

  • 编号不同,没有运行前的编号为00000000开头,运行后变成了0100000开头

  • 数据不同:填充00的大小不一样。硬盘上填充00小,内存中填充00比较大,大部分数据是一样的

2.将记事本的.exe文件读取到内存,并返回读取后在内存中的地址.

大概思路: (1)打开文件 (2)得到文件的大小 --> 读取文件到内存,然后跳转到文件末尾,查看跳转的长度 (3)根据大小申请内存 (4)把文件中内容读取到内存里 (5)返回内存编号

第一种写法:
​
#include "stdafx.h"
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
​
#define F_PATH "C:\\cntflx\\notepad.exe"
​
int Pe_Getfile_Size()
{
    FILE* fp=fopen(F_PATH,"r");
    if (!fp)
    {
        return -1;
    }
    fseek(fp,0L,SEEK_END);
    int size = ftell(fp);
    fseek(fp,0,SEEK_SET);
    fclose(fp);
    
    return size;
}
​
int FileSizes = Pe_Getfile_Size();
​
int Pe_ReadMemtory_addrs1()
{
    //定义一个文件的指针,并初始化其为NULL
    FILE* fstream = NULL;
​
    //初始化exe文件长度
    int FstreamSizes = 0;
​
    //准备打开文件notepad.exe ,读写,且是读二进制文件
    fstream = fopen(F_PATH,"ab+");
​
    //获取打开文件的exe大小
    FstreamSizes = FileSizes;
//    printf("%d \n",FstreamSizes);
​
    //申请动态内存指向FileBuffer
    int* FileBuffer = (int*)malloc(FstreamSizes);
​
    //判断申请的内存是否成功,不成功就返回0,成功就开始读exe内容写入申请的内存中
    if (FileBuffer == NULL)
    {
        return 0;
    }
    else
    {
        fread(FileBuffer,FstreamSizes,1,fstream);
    }
    memset(FileBuffer,0,Pe_Getfile_Size());
​
    //返回内存编号
    int addr = (int)FileBuffer;
    printf("%x \n",addr);
    //释放申请的内存空间
    free(FileBuffer);
    FileBuffer = NULL;
    fclose(fstream);
​
    return 0;
}
​
int main(int argc, char* argv[])
{
    Pe_ReadMemtory_addrs1();
    return 0;
}

第二种

#include "stdafx.h"
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
​
int file_length(FILE *fp);
​
void fun_02()
{
    
    // 定义一个文件指针
    FILE *fp1 = NULL;
    int FpSize = 0;  // 初始化exe文件长度
    
    // 打开文件(读和写)
    fp1 = fopen("C:\\Windows\\System32\\notepad.exe","rb");
    //获取exe大小
    FpSize = file_length(fp1);
    // 开辟一段动态内存,用FileBuffer指向
    char * FileBuffer = (char *)malloc(FpSize);    
    // 将.exe写入内存中
    if(FileBuffer != NULL)
    {
        
        fread(FileBuffer,FpSize,1,fp1);
    }
    // 返回内存编号
    int addr = (int)FileBuffer;
    printf("%x",FileBuffer);
    // 释放开辟的内存
    free(FileBuffer);
    fclose(fp1);
}
​
int file_length(FILE *fp)
{
    
    // 初始化一个计数器
    int num;
    fseek(fp,0,SEEK_END);
    num = ftell(fp);
    // 使用完毕后,要将文件指针指向文件开始
    fseek(fp,0,SEEK_SET);
    return num;
}
​
int main(int argc, char* argv[])
{
    
    fun_02();
    getchar();
    return 0;
}

3.将内存中的数据存储到一个文件中,(.exe格式),然后双击打开,看是否能够使用.

第一种

#include "stdafx.h"
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
​
#define F_PATH "C:\\cntflx\\notepad.exe"
#define W_PATH "C:\\cntflx\\newnotepad.exe"
​
int Pe_Getfile_Size()
{
    FILE* fp=fopen(F_PATH,"r");
    if (!fp)
    {
        return -1;
    }
    fseek(fp,0L,SEEK_END);
    int size = ftell(fp);
    fseek(fp,0,SEEK_SET);
    fclose(fp);
    
    return size;
}
​
int FileSizes = Pe_Getfile_Size();
​
int Pe_ReadMemtory_addrs1()
{
    //定义两个文件的指针,并初始化为NULL
    FILE* fstream1 = NULL;
    FILE* fstream2 = NULL;
    
    //初始化exe文件长度
    int FstreamSizes = 0;
    
    //准备打开文件notepad.exe ,读写,且是读二进制文件
    fstream1 = fopen(F_PATH,"ab+");
    
    //写入一个新的不存在的exe文件
    fstream2 = fopen(W_PATH,"ab+");
​
    //获取打开文件的exe大小
    FstreamSizes = FileSizes;
    //    printf("%d \n",FstreamSizes);
    
    //申请动态内存指向FileBuffer
    int* FileBuffer = (int*)malloc(FstreamSizes);
    
    //判断申请的内存是否成功,不成功就返回0
    //成功的话就开始读exe文件内容,写入到另一个exe文件中
​
    if (FileBuffer == NULL)
    {
        return 0;
    }
    else
    {
        fread(FileBuffer,FstreamSizes+1,1,fstream1);
        fwrite(FileBuffer,FstreamSizes,1,fstream2);
    }
    memset(FileBuffer,0,Pe_Getfile_Size());
    //释放堆中申请的内存,并关闭打开的文件流
​
    free(FileBuffer);
    FileBuffer = NULL;
    fclose(fstream1);
    fclose(fstream2);
    
    return 0;
}
​
int main(int argc, char* argv[])
{
    Pe_ReadMemtory_addrs1();
    return 0;
}

第二种

#include "stdafx.h"
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
​
int file_length(FILE *fp);
​
void fun_02()
{
    
    // 定义两个文件指针,一个读一个写
    FILE *fp1 = NULL;
    FILE *fp2 = NULL;
    int FpSize = 0;  // 初始化exe文件长度
    
    // 打开文件(读和写)
    fp1 = fopen("C:\\Windows\\System32\\notepad.exe","rb");
    fp2 = fopen("C:\\cntflx\\hehetest.exe","wb");
    //获取exe大小
    FpSize = file_length(fp1);
    // 开辟一段动态内存,用FileBuffer指向
    char * FileBuffer = (char *)malloc(FpSize);    
    // 将.exe写入内存中
    if(FileBuffer != NULL)
    {
        
        fread(FileBuffer,FpSize+1,1,fp1);
        fwrite(FileBuffer,FpSize,1,fp2);
        
    }
    // 释放堆中开辟的内存、关闭流
    free(FileBuffer);
    fclose(fp1);
    fclose(fp2);
    
}
​
int file_length(FILE *fp)
{
    
    // 初始化一个计数器
    int num;
    fseek(fp,0,SEEK_END);
    num = ftell(fp);
    // 使用完毕后,要将文件指针指向文件开始
    fseek(fp,0,SEEK_SET);
    return num;
    
}
​
int main(int argc, char* argv[])
{
    
    fun_02();
    getchar();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值