十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
你的想法是可以的。
成都创新互联专业为企业提供巨鹿网站建设、巨鹿做网站、巨鹿网站设计、巨鹿网站制作等企业网站建设、网页设计与制作、巨鹿企业网站模板建站服务,10余年巨鹿做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。
实际上C提供一个标准的库函数可以实现这个功能。
void *realloc(void *mem_address, unsigned int newsize);
譬如:
int *p = malloc(sizeof(int)*3);
p[0]=0;p[1]=1;p[2]=2;
p = realloc(p, sizeof(int)*4);
这个时候,p指向的前三个int的值还是1、2、3,而且可以对第四个int赋值了。realloc会自动把原来的数据复制到新的内存空间上去。
首先你要搞明白,List本身已经被定义为Node*类型,因此List*实际上是一个二级指针
你的疑问中,如果改成*list = p-next,运行应该是可以通过的。但是不推荐这样做。为什么呢?
这就要先理解FreeMem这个函数,为什么用List*做参数,而不是List。如果只是为了释放链表内存,只要一级指针就可以了,用二级指针只会增加代码的复杂程度,降低可读性。二级指针的作用就在于,在这个函数内,你可以修改这个函数的主调函数(比如main函数)中链表头结点的指针值。在这个例子中,显而易见的就是,链表释放了内存,head指针应该是NULL。
如果上面这段话你能明白的话,那么我的建议是,使用你问题中“可行”的那段代码,并添加*list = NULL;在结尾。或者这样做也可以达到同样的效果:传入参数使用一级指针,配合函数的返回值来保证功能的完整性,这样调用的时候需要诸如head = FreeMem(head);以达到释放内存后置head指针为NULL的目的。
看了楼主的追问,看来楼主对二级指针的理解还不太到位。其实mornslit兄的解释已经说清楚你这种写法的问题在哪了。我再帮你分析下:
pt = p-next;
*list = p-next;
这两种写法,效果是一样的,都是保存了下一个节点的地址(也就是p-next的值)
list = p-next;
这种写法,是保存了p这个节点的next指针的地址,通过*运算,看似可以获取next的值,其实在p被free掉之后,next指针本身的值已经不能保证了
简言之,你错在哪了:p-next是下一个节点的地址,是与p共存亡的,你可以保存p-next的值,但不应该保存它的地址
说实话,还是建议楼主先搞清楚为什么要用二级指针,杀鸡用牛刀未必一定好~
#include stdio.h
#include string.h
#include malloc.h
#define MBKSIZE 1024
typedef struct test {
int num;
char str[500];
} MTEST;
typedef struct mem {
char *mblock;
int size;
int used;
} MEM;
MEM mb;
void initmem(void)
{
mb.mblock=(char*)malloc(MBKSIZE);
mb.size=MBKSIZE;
mb.used=0;
}
void *getmem(int size)
{
if(mb.size-mb.usedsize)
{
mb.size+=MBKSIZE;
mb.mblock=(char*)realloc(mb.mblock,mb.size);
}
mb.used+=size;
return mb.mblock[mb.used-size];
}
int main(void)
{
int *pint;
double *pdbl;
char *pchr,*pstr;
MTEST* pstu,*pstue;
initmem();
pint=(int*)getmem(sizeof(int));
*pint=5;
pdbl=(double*)getmem(sizeof(double));
*pdbl=10000;
pchr=(char*)getmem(sizeof(char));
*pchr='z';
pstr=getmem(20);
strcpy(pstr,"hello world");
pstu=(MTEST*)getmem(sizeof(MTEST));
pstu-num=8;
strcpy(pstu-str,"hello c");
pstue=(MTEST*)getmem(sizeof(MTEST));
pstue-num=8;
strcpy(pstue-str,"hello c++");
printf("int: %d,double: %.2lf\nchar: %c\n\
str: %s\nstu.num: %d,stu.str: %s\n"\
,*pint,*pdbl,*pchr,pstr,pstu-num,pstu-str);
return 0;
}
C语言实现,非伪代码,完全可以满足LZ的要求。。
一般的讲,内存里边虽然说有*G的空间,但有些地方只是挂名存在,实际上是不存在的,所以访问了就会出错,所以就要判断内存是不是为有效地址,
就要用到VirtualQuery获取指定内存属性, 根据属性来判断能不能进行读取,
如果能读取就从调用VirtualQuery中得到的内存信息minfo中获取当前内存地址的有效区域的大小,然后再进行读取. 你可以用VC调试来看看,不能访问的内存就用?号来表示.由于搜所内存是一种运算量庞大的工作,所以,在对比处理要作速度优化处理. 如果数据大于4字节,请用 long 的数据格式来作对比运算, long 是 char 的处理速度的三倍以上,(个人测试的) 用long处理前端数据,再用 char 作收尾工作. 这是对比处理了.流程就有以下:
判断地址的有效性-定好搜所范围-进行对比-输出结果.
StartAdd 开始地址
EndAdd 结束地址
Data 查找的数据
DataSize 数据大小
void *FindMemory(DWORD StartAdd,DWORD EndAdd,void *Data,DWORD DataSize)
{
MEMORY_BASIC_INFORMATION minfo;
DWORD rt;
while(StartAddEndAdd)
{
::VirtualQuery((void*)StartAdd,minfo,sizeof(MEMORY_BASIC_INFORMATION));
if(minfo.AllocationProtect)
if(minfo.State==MEM_COMMIT||minfo.State==MEM_FREE)
{
char *s=(char*)StartAdd,*e=s+minfo.RegionSize;
for(;ses+DataSize=e;s++)
if(memcmp(s,Data,DataSize)==0)
return s;
}
StartAdd=(DWORD)minfo.BaseAddress+minfo.RegionSize;
}
return 0;
}