国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

c語言-動態(tài)內(nèi)存管理

這篇具有很好參考價(jià)值的文章主要介紹了c語言-動態(tài)內(nèi)存管理。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。


一、為什么會有動態(tài)內(nèi)存管理

1.我們一般的開辟空間方式:

int a = 0;//申請4個(gè)字節(jié)空間
int arr[10] = { 0 };//申請40個(gè)字節(jié)空間

2.這樣開辟空間的特點(diǎn)

(1)申請的空間大小是固定的
(2)像數(shù)組那樣一開始就要確定大小,一旦確定大小就不能改變了

3.動態(tài)內(nèi)存

對于程序來說上述的內(nèi)存申請是不能滿足 因此為了能夠?qū)?nèi)存進(jìn)行調(diào)整,C語言引入了動態(tài)內(nèi)存開辟,讓程序員自己可以申請和釋放空間,就比較靈活了。

二、申請內(nèi)存函數(shù)

以下動態(tài)申請的內(nèi)存都是向堆區(qū)申請的,
并且都申請內(nèi)存的函數(shù)和釋放函數(shù)都包含在頭文件 :#include<stdlib.h>

1、malloc

(1)返回類型和參數(shù):

void* malloc(size_t size);//返回類型為 void*  ,參數(shù)為正整數(shù)單位是字節(jié)

因?yàn)榉祷仡愋蜑?void*,所以在malloc函數(shù)是不知道我們想要申請什么類型的空間,面對這種情況我們要將返回的類型進(jìn)行強(qiáng)制類型轉(zhuǎn)換,這樣就能返回我們需要的類型了,參數(shù)是申請的大小

(2)作用:

向內(nèi)存申請一塊連續(xù)的空間,并返回指向這塊空間的的指針

(3)注意:

a.在申請完之后我們還要判斷是否成功申請
當(dāng)申請失敗時(shí)會返回NULL
當(dāng)申請成功后就返回指向這塊空間的的指針,這樣可以正常使用這塊空間了
b.如果參數(shù) size 為0,malloc的行為是標(biāo)準(zhǔn)是未定義的,取決于編譯器

(4)使用:

int main() {
	int* p = (int*)malloc(sizeof(int) * 10);//向內(nèi)存申請40個(gè)字節(jié)空間
	if (p == NULL)//判斷是否申請成功
		return 1;//失敗直接放回
	for (int i = 0; i < 10; i++)//成功就正常使用
		*(p + i) = i;
	for (int i = 0; i < 10; i++)//打印
		printf("%d ", *(p + i));
	return 0;
}

運(yùn)行結(jié)果:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享

2、free

(1)返回類型和參數(shù):

void free( void* p)//參數(shù)為向動態(tài)內(nèi)存申請的空間的指針,返回類型為空

(2)作用:

專門進(jìn)行對動態(tài)內(nèi)存的釋放和回收

(3)注意:

a.當(dāng)釋放的內(nèi)存不是動態(tài)開辟的,這是free未定義的
b.當(dāng)p是NULL時(shí),free函數(shù)什么事都不發(fā)生
c.當(dāng)我們將p指向的空間釋放后,要將p置空,不然p就成野指針了

(4)使用

在我們上一個(gè)代碼中,并未對malloc函數(shù)開辟的空間進(jìn)行釋放,其實(shí)這是不對的,這會造成內(nèi)存泄漏。 那么我們就來用一下free函數(shù)吧

int main() {
	int* p = (int*)malloc(sizeof(int) * 10);//向內(nèi)存申請40個(gè)字節(jié)空間
	if (p == NULL)//判斷是否申請成功
		return 1;//失敗直接放回
	for (int i = 0; i < 10; i++)//成功就正常使用
		*(p + i) = i;
	for (int i = 0; i < 10; i++)//打印
		printf("%d ", *(p + i));
	free(p);//釋放
	p = NULL;//及時(shí)置空,防止出現(xiàn)野指針
	return 0;
}

這樣代碼才算完整。

3、calloc

(1)返回類型和參數(shù):

void *calloc(size_t n,size_t  size);

返回類型為 void* ,所以和malloc一樣想要什么類型的空間就進(jìn)行強(qiáng)制轉(zhuǎn)換類型即可,第一個(gè)參數(shù)為申請的個(gè)數(shù),第二個(gè)參數(shù)為申請的類型的空間大?。▎挝粸樽止?jié))

(2)作用:

申請一塊連續(xù)的空間,并將空間的內(nèi)容全部初始化為0,然后返回指向這塊空間的指針

(3)注意:

a.在申請完之后我們還要判斷是否成功申請
當(dāng)申請失敗時(shí)會返回NULL
當(dāng)申請成功后就返回指向這塊空間的的指針,這樣可以正常使用這塊空間了
b.如果參數(shù) size 為0,malloc的行為是標(biāo)準(zhǔn)是未定義的,取決于編譯器
c.與malloc的區(qū)別就是calloc會將申請的空間初始化,這樣使用時(shí)更方便

(4)使用:

int main() {
	int* p = (int*)calloc(10,sizeof(int));//申請
	if (p == NULL) {//判斷
		printf("NULL");
		return 1;
	}
	//使用
	for (int i = 0; i < 10; i++)
		*(p + i) = i;
	for (int i = 0; i < 10; i++)
		printf("%d ", *(p + i));
	free(p);//同樣的釋放空間
	p = NULL;//置空
	return 0;
}

運(yùn)行結(jié)果:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享

4、realloc

(1)返回類型和參數(shù):

void *realloc(void * p ,size_t size);

返回類型為 void* 所以和calloc一樣想要什么類型就強(qiáng)制類型轉(zhuǎn)換,第一個(gè)參數(shù)p為指向想要的改變的空間的 指針,第二參數(shù)為改變的大?。▎挝粸樽止?jié))

(2)作用:

在原來的動態(tài)內(nèi)存的空間上增大或者縮小,并返回改變后指向新的空間的指針

(3)注意:

a.開辟失敗返回空指針
b.開辟的新的空間時(shí)有兩種開辟的方式,第一種是我們原本的空間后面有足夠的空間,那樣直接在原來的空間后面擴(kuò)容,第二種是我們原本的空間后面沒有足夠的空間,那樣的話,系統(tǒng)就會在內(nèi)存上找一塊適合的空間重新開辟,并將原來空間的內(nèi)容復(fù)雜過去,再將原來的空間銷毀。
由于開辟的情況有兩種,所以我們使用時(shí)要注意開辟空間失敗這種情況
如:我們使用了第二種情況開辟空間、并直接用原來的指針去接收指向開辟的空間的指針,如果開辟失敗的話返回NULL,這導(dǎo)致原來的數(shù)據(jù)會丟失。
所以為了解決這個(gè)隱患,我們可以重新定義一個(gè)指針來接收,判斷不為空再將該指針賦給原來的指針。

圖:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享
(4)使用:

int main() {
	//先用動態(tài)內(nèi)存開辟一個(gè)空間
	int* p = (int*)calloc(10, sizeof(int));
	if (p == NULL)
		return 1;
	for (int i = 0; i < 10; i++)
		*(p + i) = i;
	for (int i = 0; i < 10; i++)
		printf("%d ", *(p + i));
	printf("\n");
	//使用realloc增加空間
	int* pp = (int*)realloc(p, sizeof(int) * 15);//再申請一個(gè)指針變量來接收
	if (pp == NULL)
		return 1;
	else
		p = pp;//不為空再賦給原來的指針
	for (int i = 10; i < 15; i++)
		*(p + i) = i;
	for (int i = 10; i < 15; i++)
		printf("%d ", *(p + i));
	free(p);//最后不要忘記了釋放并置空
	p = NULL;
	return 0;
}

運(yùn)行結(jié)果:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享

三、常見的動態(tài)內(nèi)存的錯誤

1、對NULL指針的解引用操作

void test()
 {
 int *p = (int *)malloc(INT_MAX/4);//開辟空間
 //這里我們不知道是否開辟成功
 *p = 20;//如果p的值是NULL,就會有問題
 free(p);
 p=NULL;
 }

這里的問題是不知道p為不為NULL
改:

void test()
 {
 int *p = (int *)malloc(INT_MAX/4);//開辟空間
 if(p!=NULL)
 *p = 20;
 free(p);
 p=NULL;
 }

2 、對動態(tài)開辟空間的越界訪問

void test()
 {
 int i = 0;
 int *p = (int *)malloc(10*sizeof(int));
 if(NULL == p)
 {
 exit(EXIT_FAILURE);
 }
 for(i=0; i<=10; i++)
 {
 *(p+i) = i;//當(dāng)i是10的時(shí)候越界訪問
 }
 free(p);
 p=NULL;
 }

改:

void test()
 {
 int i = 0;
 int *p = (int *)malloc(10*sizeof(int));
 if(NULL == p)
 {
 exit(EXIT_FAILURE);
 }
 for(i=0; i<10; i++)//當(dāng)我們改成<10之后i就不會到10,也就不會越界了
 {
 *(p+i) = i;
 }
 free(p);
 p=NULL;
 }

3 、對非動態(tài)開辟內(nèi)存使用free釋放

 void test()
 {
 int a = 10;
 int *p = &a;
 free(p);//ok?
 }

這種行為在free函數(shù)中未定義,最好不要使用
4 、使用free釋放?塊動態(tài)開辟內(nèi)存的?部分

void test()
 {
 int *p = (int *)malloc(100);
 p++;
 free(p);//p不再指向動態(tài)內(nèi)存的起始位置
 }

這種行為會導(dǎo)致內(nèi)存泄漏
5 、對同?塊動態(tài)內(nèi)存多次釋放

void test()
 {
 int *p = (int *)malloc(100);
 free(p);
 free(p);//重復(fù)釋放
 }

當(dāng)出現(xiàn)這種情況程序會崩掉
6、 動態(tài)開辟內(nèi)存忘記釋放(內(nèi)存泄漏)

void test()
 {
 int *p = (int *)malloc(100);
 if(NULL != p)
 {
 *p = 20;
 }
 }
int main()
 {
 test();
 while(1);
 }

這種未對申請的空間釋放,會導(dǎo)致內(nèi)存泄漏

四、練習(xí)

1、請問運(yùn)行Test 函數(shù)會有什么樣的結(jié)果?

void GetMemory(char *p)
 {
 p = (char *)malloc(100);
 }
void Test(void)
 {
 char *str = NULL;
 GetMemory(str);
 strcpy(str, "hello world");
 printf(str);
 }

運(yùn)行結(jié)果:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享
什么都沒有輸出,這是為什么呢?
這是因?yàn)檎{(diào)用GetMemory函數(shù)時(shí)使用的是傳值調(diào)用,p雖然申請到了空間,但是并沒有改變str的值,所以str=NULL,所以什么內(nèi)容都沒有打印,
改;我們可以將傳值調(diào)用改為傳址調(diào)用
如:

void GetMemory(char** p)
{
	*p = (char*)malloc(100);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str);
	strcpy(str, "hello world");
	printf(str);
}
int main() {
	Test();

	return 0;
}

運(yùn)行結(jié)果:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享
成功打印
2、請問運(yùn)行Test 函數(shù)會有什么樣的結(jié)果?

char *GetMemory(void)
 {
 char p[] = "hello world";
 return p;
 }
void Test(void)
 {
 char *str = NULL;
 str = GetMemory();
 printf(str);
 }

運(yùn)行結(jié)果:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享
出現(xiàn)了隨機(jī)值,這是為什么呢?
因?yàn)閜是在棧區(qū)創(chuàng)建,當(dāng)函數(shù)結(jié)束后該p指向的空間也會銷毀然后返還給內(nèi)存,此時(shí)將p傳給str之后,str就會變成野指針,它指向的空間打印出來的就是隨機(jī)值了
改:我們可以用動態(tài)內(nèi)存
如:

void GetMemory(char** p)
{
	*p = (char*)malloc(100);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str);
	strcpy(str, "hello world");
	printf(str);
}
int main() {
	Test();

	return 0;
}

運(yùn)行結(jié)果:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享
3、請問運(yùn)行Test 函數(shù)會有什么樣的結(jié)果?

void GetMemory(char **p, int num)
 {
 *p = (char *)malloc(num);
 }
void Test(void)
 {
 char *str = NULL;
 GetMemory(&str, 100);
 strcpy(str, "hello");
 printf(str);
 }

運(yùn)行結(jié)果:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享
輸出正確。但是這里的問題時(shí)沒有釋放動態(tài)內(nèi)存
改:

void GetMemory(char** p, int num)
{
	*p = (char*)malloc(num);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
	free(str);
	str = NULL;
}
int main() {
	Test();
	return 0;
}

4、請問運(yùn)行Test 函數(shù)會有什么樣的結(jié)果?

void Test(void)
 {
 char *str = (char *) malloc(100);
 strcpy(str, "hello");
 free(str);
 if(str != NULL)
 {
 strcpy(str, "world");
 printf(str);
 }
 }

運(yùn)行結(jié)果:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享
雖然結(jié)果正確,但是其實(shí)是有問題的
1.因?yàn)閟tr存儲的地址不會改變,應(yīng)該手動置空,但是它釋放空間后沒有置空
2.使用釋放的空間(這塊空間已經(jīng)還給系統(tǒng)了)
3.為什么還能打印world呢?那是因?yàn)樵搲K空間沒有被覆蓋,world還在那里
我們可以試試再他前面再申請一次動態(tài)內(nèi)存看看

void Test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
	if (str != NULL)
	{
		strcpy(str, "world");
		char* str1 = (char*)malloc(100);
		printf(str);
	}
}
int main() {
	Test();
	return 0;
}

運(yùn)行結(jié)果:
c語言-動態(tài)內(nèi)存管理,c語言主要知識點(diǎn),c語言,算法,服務(wù)器,開發(fā)語言,筆記,經(jīng)驗(yàn)分享
world被覆蓋了,就打印不出了
改:我們可以釋放后置空,就不會出現(xiàn)這種情況了

void Test(void)
 {
 char *str = (char *) malloc(100);
 strcpy(str, "hello");
 free(str);
 str=NULLif(str != NULL)
 {
 strcpy(str, "world");
 printf(str);
 }
 }

以上就是我的分享了,如果有什么錯誤,歡迎在評論區(qū)留言。
最后,謝謝大家的觀看!文章來源地址http://www.zghlxwxcb.cn/news/detail-762913.html

到了這里,關(guān)于c語言-動態(tài)內(nèi)存管理的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 計(jì)算機(jī)語言知識點(diǎn)梳理

    python是一門強(qiáng)類型、動態(tài)型、解釋型語言語言 JavaScript是一門弱類型、動態(tài)性、解釋型語言 typescript是一門強(qiáng)類型、靜態(tài)型、編譯型語言 Java是一門強(qiáng)類型、靜態(tài)型、編譯型語言 變量大小寫區(qū)分 html css sql java javascript python typescript c 弱類型語言和強(qiáng)類型語言 強(qiáng)類型語言也稱為強(qiáng)

    2024年02月09日
    瀏覽(29)
  • 【C語言】指針知識點(diǎn)筆記(2)

    【C語言】指針知識點(diǎn)筆記(2)

    目錄 一、野指針 二、assert斷言 三、指針的使用和傳址調(diào)用 四、數(shù)組名的理解 五、使用指針訪問數(shù)組

    2024年01月18日
    瀏覽(23)
  • 【詳解】C語言冷門知識點(diǎn)之--位段

    【詳解】C語言冷門知識點(diǎn)之--位段

    下面是維基百科對位段的解釋: ??位段(或稱“位域”,Bit field)為一種數(shù)據(jù)結(jié)構(gòu),可以把數(shù)據(jù)以位的形式緊湊的儲存,并允許程序員對此結(jié)構(gòu)的位進(jìn)行操作。這種數(shù)據(jù)結(jié)構(gòu)的好處: 可以使數(shù)據(jù)單元節(jié)省儲存空間,當(dāng)程序需要成千上萬個(gè)數(shù)據(jù)單元時(shí),這種方法就顯得尤為重

    2024年02月16日
    瀏覽(45)
  • 單片機(jī)----匯編語言入門知識點(diǎn)

    單片機(jī)----匯編語言入門知識點(diǎn)

    目錄 匯編語句的格式 匯編語句的兩個(gè)基本語句 子程序的調(diào)用 查表程序設(shè)計(jì) 1.x和y均為單字節(jié)數(shù)的查表程序設(shè)計(jì) 2.x為單字節(jié)數(shù)y為雙字節(jié)數(shù)的查表程序設(shè)計(jì) 3.x和y均為雙字節(jié)數(shù)的查表程序設(shè)計(jì) 分支轉(zhuǎn)移程序設(shè)計(jì) 1.單分支選擇結(jié)構(gòu) 2.多分支選擇結(jié)構(gòu) 循環(huán)程序設(shè)計(jì) (1) 計(jì)數(shù)循環(huán)控

    2024年04月28日
    瀏覽(22)
  • 帶寬管理:知識點(diǎn)概述及防火墻帶寬管理實(shí)驗(yàn)

    帶寬管理:知識點(diǎn)概述及防火墻帶寬管理實(shí)驗(yàn)

    目錄 一、帶寬管理技術(shù)介紹 1.1 基本概念: 1.2 帶寬管理原理介紹: 1.3 接口帶寬原理: 1.4 帶寬策略原理: 1.5 帶寬通道原理 1.6 帶寬復(fù)用 二、帶寬管理實(shí)驗(yàn) 1.1 基本概念: 帶寬管理對通過自身的流量進(jìn)行管理和控制:提供帶寬保證。 提供帶寬限制。 提供連接數(shù)限制功能。

    2024年02月15日
    瀏覽(27)
  • C++入門知識點(diǎn)——解決C語言不足

    C++入門知識點(diǎn)——解決C語言不足

    ????????????????????????Take your time ! ???????????????????????? ??個(gè)人主頁:??????大魔王?????? ??所屬專欄:??魔王的修煉之路–C++?? 如果你覺得這篇文章對你有幫助,請?jiān)谖恼陆Y(jié)尾處留下你的 點(diǎn)贊 ??和 關(guān)注 ??,支持一下博主

    2024年02月12日
    瀏覽(22)
  • C語言指針入門學(xué)習(xí)、知識點(diǎn)梳理(四)

    本篇內(nèi)容:指針星號的三種含義以及指針在函數(shù)調(diào)用時(shí),與實(shí)參、形參的變量傳遞關(guān)系,如何通過被調(diào)函數(shù)修改主調(diào)函數(shù)普通變量的值。 傳送門: C語言指針入門學(xué)習(xí)、概念梳理(一) C語言指針入門學(xué)習(xí)、概念梳理(二) C語言指針入門學(xué)習(xí)、知識點(diǎn)梳理(三) C語言指針入門

    2024年02月09日
    瀏覽(32)
  • C語言:數(shù)組、字符串知識點(diǎn)整理:

    補(bǔ)充 :數(shù)組長度= sizeof(arr)/sizeof(arr[0]) 注意: ?。?! 不適用于當(dāng)arr 充當(dāng)形參時(shí)(函數(shù)傳參) ?。?! 因?yàn)楹瘮?shù) 傳遞 的是 int arr[0] 的 地址(指針) ,而 不是數(shù)組內(nèi)容 , 若在此情況計(jì)算整形數(shù)組長度 ????????在X86系統(tǒng)下,指針大小為 4 ,所以計(jì)算結(jié)果為4/4=1; ??????

    2024年03月10日
    瀏覽(25)
  • 【C語言】動態(tài)內(nèi)存管理基礎(chǔ)知識——動態(tài)通訊錄,如何實(shí)現(xiàn)通訊錄容量的動態(tài)化

    【C語言】動態(tài)內(nèi)存管理基礎(chǔ)知識——動態(tài)通訊錄,如何實(shí)現(xiàn)通訊錄容量的動態(tài)化

    動態(tài)內(nèi)存管理的函數(shù)有:malloc,calloc,ralloc,free,本文講解動態(tài)內(nèi)存函數(shù)和使用,如何進(jìn)行動態(tài)內(nèi)存管理,實(shí)現(xiàn)通訊錄聯(lián)系人容量的動態(tài)化,對常見動態(tài)內(nèi)存錯誤進(jìn)行總結(jié)。 ???????? ? ? ? ? ? ? ? ? ??? 豬巴戒 :個(gè)人主頁? ??????????????? 所屬專欄 :《C語言進(jìn)階》

    2024年02月04日
    瀏覽(44)
  • 【C語言】讓你不再害怕“指針”【知識點(diǎn)詳解】

    【C語言】讓你不再害怕“指針”【知識點(diǎn)詳解】

    目錄 一.什么是指針為什么需要指針? 1.什么是指針? 2.為什么需要指針? 以一個(gè)代碼為例觀察地址:(這里我們可以通過調(diào)試和打印兩種方式觀察) 1.調(diào)試觀察: 2.打印觀察(地址是用%p 打?。?二.地址編號的來源指針變量的大小 產(chǎn)生來源 指針變量大小 三.指針類型??

    2024年02月08日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包