项目学习3 以一个例子来讲解函数指针的间接赋值和程序使用内存模型图

这个程序是将读取文件中的多行内容这个功能封装成一个函数,并在main函数中使用。

#include <iostream>
#include <fstream>
#include <string>
#include <string.h>
using namespace std;

#define TEXT "./1.txt"//该宏定义是定义一个读取文件,就是在程序所在目录下的1.txt文件
//这个函数是读取文件规定的前line行,并显示在屏幕上,其中ifs是输入参数,是输入需要读取的文件流,p
//是输出参数,输出读取内容所存储的区域地址,line是输入输出参数,输入需要读取的行数,输出实际读取的行数
int getfilecontent(ifstream *ifs, char ***p, int *line)
{
	char **tempP = new char*[*line];//tempP是指向一个字符串数组的指针
	int i = 0;
	if (tempP == NULL)//创建动态指针时,这个一定要判断,因为如果堆区内存不满足要求,就会返回NULL值
	{
		return -1;
	}
	for (; i < *line; ++i)
	{
		tempP[i] = new char[100];
		memset(tempP[i], 0, 100);//将tempP[i]初始化,这一步也是必须的,注意动态指针不能用sizeof来获得指针长度,只能定义长度常量或者自己手写
		ifs->getline(tempP[i], 100);//读取一行的文件内容,并且下一次调用,就自动读取下一行
		cout << tempP[i] << endl;
	}//*********************************************断点
	*line = i;//将真正读取的行数放到line中
	*p = tempP;//将读取内容存储地址存放到p中
	return 0;
	
}
//在所有内容都读完以后,需要释放动态指针,这是释放动态指针的子步骤
int getfilecontent_free_sub(char **p, int line)
{
	if (p == NULL)
		return 0;
	for (int i = 0; i < line; ++i)
	{
		delete [] p[i];
	}
	delete [] p;
	return 0;
}
//释放动态地址的总步骤
int getfilecontent_free(char ***p, int line)
{
	getfilecontent_free_sub(*p, line);
	*p = NULL;
	return 0;
}
int main()
{
	ifstream myifs;
	myifs.open(TEXT);
	int myline = 3;
	char **myp=NULL;
	int flag=getfilecontent(&myifs, &myp, &myline);
	if (flag != 0)
	{
		cout << "getfilecontent is error";
		return 0;
	}
	getfilecontent_free(&myp, myline);
	system("pause");
	return 0;
}

一、程序执行过程中的内存使用情况

预备知识

一个由C/C++编译的程序占用的内存分为以下几个部分 :

1、栈区(stack)— 由编译器自己主动分配释放 。存放函数的參数值,动态局部变量的值等。其操作方式类似于数据结构中的栈(先进后出)。
2、堆区(heap) — 一般由程序员分配释放(就是动态指针,用new或者malloc创建),需要用delete或者free释放,注意它与数据结构中的堆是两回事(数据结构中的堆是堆二叉树),分配方式倒是类似于链表。
3、全局区(静态区)(static)—。全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的还有一块区域。 - 程序结束后有系统释放 
4、文字常量区—常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。

下图的内存分配是执行到断点处内存的分布情况

其中有几个地方需要注意:

1.在执行子函数时,其实是在栈中创建形参变量,再把实参值赋给形参变量。

2.所有的变量名在转变成汇编语言时都是不存在的,变量名都会被连接器转换成具体的存储地址,所以这些变量只是为了方便人理解的。

3.一般字符串常量放在文字常量区,(有个疑问,是不是文字常量区就在全局区当中,没查到确切的资料)

二、使用多级指针进行间接赋值

间接赋值步骤:

1.定义变量(一个形参,一个实参)

2.建立关联(将实参取地址传给形参)

3.在被调用函数中的实参的地址去间接修改实参的值(用N级形参去修改N-1级实参的值)

在程序中体现如下

int getfilecontent(ifstream *ifs, char ***p, int *line);

int main()
{
    ifstream myifs;
    myifs.open(TEXT);
    int myline = 3;
    char **myp=NULL;
    int flag=getfilecontent(&myifs, &myp, &myline);

ifs,p,line都是形参,myifs,myline,myp都是实参,通过实参取地址,传给形参,然后修改实参的值

这样的好处是有利于程序的保密性,让使用函数的人不难以推测函数如何去运行的。

猜你喜欢

转载自blog.csdn.net/qq_34489443/article/details/88948354