你的想法是可以的。
成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供巨鹿網(wǎng)站建設(shè)、巨鹿做網(wǎng)站、巨鹿網(wǎng)站設(shè)計(jì)、巨鹿網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、巨鹿企業(yè)網(wǎng)站模板建站服務(wù),10余年巨鹿做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
實(shí)際上C提供一個(gè)標(biāo)準(zhǔn)的庫函數(shù)可以實(shí)現(xiàn)這個(gè)功能。
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);
這個(gè)時(shí)候,p指向的前三個(gè)int的值還是1、2、3,而且可以對第四個(gè)int賦值了。realloc會自動把原來的數(shù)據(jù)復(fù)制到新的內(nèi)存空間上去。
首先你要搞明白,List本身已經(jīng)被定義為Node*類型,因此List*實(shí)際上是一個(gè)二級指針
你的疑問中,如果改成*list = p-next,運(yùn)行應(yīng)該是可以通過的。但是不推薦這樣做。為什么呢?
這就要先理解FreeMem這個(gè)函數(shù),為什么用List*做參數(shù),而不是List。如果只是為了釋放鏈表內(nèi)存,只要一級指針就可以了,用二級指針只會增加代碼的復(fù)雜程度,降低可讀性。二級指針的作用就在于,在這個(gè)函數(shù)內(nèi),你可以修改這個(gè)函數(shù)的主調(diào)函數(shù)(比如main函數(shù))中鏈表頭結(jié)點(diǎn)的指針值。在這個(gè)例子中,顯而易見的就是,鏈表釋放了內(nèi)存,head指針應(yīng)該是NULL。
如果上面這段話你能明白的話,那么我的建議是,使用你問題中“可行”的那段代碼,并添加*list = NULL;在結(jié)尾。或者這樣做也可以達(dá)到同樣的效果:傳入?yún)?shù)使用一級指針,配合函數(shù)的返回值來保證功能的完整性,這樣調(diào)用的時(shí)候需要諸如head = FreeMem(head);以達(dá)到釋放內(nèi)存后置head指針為NULL的目的。
看了樓主的追問,看來樓主對二級指針的理解還不太到位。其實(shí)mornslit兄的解釋已經(jīng)說清楚你這種寫法的問題在哪了。我再幫你分析下:
pt = p-next;
*list = p-next;
這兩種寫法,效果是一樣的,都是保存了下一個(gè)節(jié)點(diǎn)的地址(也就是p-next的值)
list = p-next;
這種寫法,是保存了p這個(gè)節(jié)點(diǎn)的next指針的地址,通過*運(yùn)算,看似可以獲取next的值,其實(shí)在p被free掉之后,next指針本身的值已經(jīng)不能保證了
簡言之,你錯(cuò)在哪了:p-next是下一個(gè)節(jié)點(diǎn)的地址,是與p共存亡的,你可以保存p-next的值,但不應(yīng)該保存它的地址
說實(shí)話,還是建議樓主先搞清楚為什么要用二級指針,殺雞用牛刀未必一定好~
#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語言實(shí)現(xiàn),非偽代碼,完全可以滿足LZ的要求。。
一般的講,內(nèi)存里邊雖然說有*G的空間,但有些地方只是掛名存在,實(shí)際上是不存在的,所以訪問了就會出錯(cuò),所以就要判斷內(nèi)存是不是為有效地址,
就要用到VirtualQuery獲取指定內(nèi)存屬性, 根據(jù)屬性來判斷能不能進(jìn)行讀取,
如果能讀取就從調(diào)用VirtualQuery中得到的內(nèi)存信息minfo中獲取當(dāng)前內(nèi)存地址的有效區(qū)域的大小,然后再進(jìn)行讀取. 你可以用VC調(diào)試來看看,不能訪問的內(nèi)存就用?號來表示.由于搜所內(nèi)存是一種運(yùn)算量龐大的工作,所以,在對比處理要作速度優(yōu)化處理. 如果數(shù)據(jù)大于4字節(jié),請用 long 的數(shù)據(jù)格式來作對比運(yùn)算, long 是 char 的處理速度的三倍以上,(個(gè)人測試的) 用long處理前端數(shù)據(jù),再用 char 作收尾工作. 這是對比處理了.流程就有以下:
判斷地址的有效性-定好搜所范圍-進(jìn)行對比-輸出結(jié)果.
StartAdd 開始地址
EndAdd 結(jié)束地址
Data 查找的數(shù)據(jù)
DataSize 數(shù)據(jù)大小
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;
}