动态内存管理

  首先应该明白对象的三种内部的存储方式:自动存储,静态存储,和动态存储。当执行离开当期程序块的时候,堆栈指针返回到它进入程序块

之前的地方,有效的销毁了那个程序块的自动变量。重新进入这个块会再次创建所有的自动变量。静态对象声明或者在文件域中。动态对象是存在系统调用

的在运行期中创建并且保存在堆中,这是一种特殊的留给用户控制的数据区。


下面是C++/C中常见的动态内存的技术

1.参差数组

//在编译期间并不知道多大空间存储一个对象使用堆栈很方便
//在C中处理文本文件习惯是为文本每一行分配堆栈空间,在一个指向char类型的指针数组里面存储地址

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define  MAXLINE 1024

static int scomp(const void*,const void*);

int main(int argc,char**argv){
	int i,n;
	char*strings[MAXLINE],buf[BUFSIZ];

	if (argc>1)
	 freopen(argv[1],"r",stdin);

	for (n=0;n<MAXLINE&&fgets(buf,BUFSIZ,stdin);++n)
	{
		strings[n] = (char*)malloc(strlen(buf)+1);
		assert(strings[n]);
		strcpy(strings[n],buf);
	}

	qsort(strings,n,sizeof strings[0],scomp);

	for (i=0;i<n;++i)
	{
		fputs(strings[i],stdout);
		free(strings[i]);
	}

	return 0;
}

static int scomp(const void* p1,const void* p2){
	char *a = *(char**)p1;
	char *b = *(char**)p2;
	return strcmp(a,b);
}

2.在标准C中使用堆

头文件<stdlib.h>使用动态分配声明了4个函数
1.void*malloc(size_t,siz);返回一个指向siz大小的第一个字节的指针通常分配单个对象
2.void*calloc(size_t nelems,size_t elem_size)返回指向nelems*elem_size字节的指针通常分配对象数组
3.void*realloc(void*ptr,size_t siz);用于扩展或者缩小堆栈的分配ptr必须源于上次malloc,calloc或者realloc调用
4.void free(void*ptr)使用以前分配的堆栈内存去可以重用

//getargs.c
#include <stdio.h>

//返回一个指针指向动态分配大小的。字符串的参差数组
extern char**arglist(int ,char**,int*);
extern void free_arglist(int ,char**);

int main(int argc,char**argv){
	int i,nargs;
	char**args = arglist(--argc,++argv,&nargs);

	for (i=0;i<nargs;++i)
	 printf("%d: %s\n",i,args[i]);
	free_arglist(nargs,args);
	return 0;
}


//arglist.c从文件递归的读取参数
//从文件递归的读取参数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define CHUNK 10 //重新分配的数量
static char**args;//参数列表
static int nleft;//不同的参数位置
static int nargs;//参数的数量

//私有函数
//用于处理间接文件参数
static void expand(FILE*f);
static void add(char*arg);



char**arglist(int old_nargs,char** old_args,int* new_nargs){
	int i;

	//最初的分配
	args = (char**)calloc(old_nargs,sizeof(char*));//分配字符串数组
	assert(args);
	nleft = old_nargs;
	nargs = 0;

	//处理每个命令行参数
	for (i=0;i<old_nargs;++i)
	{
		if (old_args[i][0] == '@')
		{
			//打开参数文件
			FILE*f = fopen(old_args[i]+1,"r");
			if (f)
			{
				expand(f);
				fclose(f);
			}
		}
		else
			add(old_args[i]);
	}

	*new_nargs = nargs;
	return args;

}


void free_arglist(int n,char**av){
	int i;
	for (i=0;i<n;++i)
	 free(av[i]);
	free(av);
}

//从文件中继续解析命令行参数
static void expand(FILE*f){
	char token[BUFSIZ];

	while(fscanf(f,"%s",token)==1)
		if (token[0] =='@')
		{
			FILE* g = fopen(token+1,"r");
			if (g)
			{
				expand(g);
				fclose(g);
			}
		}
		else
			add(token);
}



//加入新的命令行参数6
static void add(char*arg){
	if (nleft==0)
	{
		//扩大参数列表
		args = (char**)realloc(args,(nargs+CHUNK)*sizeof(char*));
		assert(args);
		nleft = CHUNK;
	}

	//为存储参数分配空间
	args[nargs] = (char*)malloc(strlen(arg)+1);
	assert(args[nargs]);
	strcpy(args[nargs++],arg);
	--nleft;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值