最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言中動(dòng)態(tài)內(nèi)存分配malloc、calloc和realloc函數(shù)解析

 更新時(shí)間:2022年03月10日 11:15:20   作者:寄一片海給你  
C語(yǔ)言跟內(nèi)存申請(qǐng)相關(guān)的函數(shù)主要有 alloca、calloc、malloc、free、realloc等,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中動(dòng)態(tài)內(nèi)存分配malloc、calloc和realloc函數(shù)的相關(guān)資料,需要的朋友可以參考下

前言

有時(shí)候我們需要的空間大小不確定,需要隨著程序需要的空間而變化, 那以數(shù)組開(kāi)辟的固定大小的空間就不適用了, 這時(shí)候我們就需要?jiǎng)討B(tài)分配開(kāi)辟空間了。當(dāng)空間不夠時(shí)就擴(kuò)容。動(dòng)態(tài)開(kāi)辟是在堆區(qū)開(kāi)辟一塊連續(xù)可用空間,并返回這塊空間的地址。有三種函數(shù)malloc, calloc和realloc。我們動(dòng)態(tài)內(nèi)存分配就在堆區(qū)開(kāi)辟空間

上面的四個(gè)區(qū)只有堆區(qū)的空間是需要手動(dòng)釋放的

free函數(shù)

free函數(shù)是專門用來(lái)對(duì)動(dòng)態(tài)開(kāi)辟內(nèi)存的回收和釋放的。當(dāng)我們不需要再使用動(dòng)態(tài)開(kāi)辟的空間時(shí),一定要free釋放空間,因?yàn)槭窃诙焉祥_(kāi)辟的空間,所以不會(huì)隨著出了作用域而銷毀,需要我們free釋放,避免內(nèi)存泄漏,并置空(將指針置為NULL),避免形成野指針。

內(nèi)存釋放是標(biāo)記刪除, 只會(huì)修改當(dāng)前空間的所屬狀態(tài),并不會(huì)清除空間內(nèi)容。

當(dāng)然內(nèi)存泄漏也不是都有危害,但為了養(yǎng)成良好的代碼習(xí)慣,動(dòng)態(tài)開(kāi)辟后一定要free

void free (void* ptr);

1.如果參數(shù)ptr指向的內(nèi)存空間不是動(dòng)態(tài)內(nèi)存開(kāi)辟的,那free函數(shù)的行為是未定義的,就會(huì)報(bào)錯(cuò),所以free函數(shù)是針對(duì)動(dòng)態(tài)開(kāi)辟的空間

2.如果ptr是 NULL空指針,那么free函數(shù)什么都不做。

下面我們來(lái)實(shí)現(xiàn)一下。

動(dòng)態(tài)內(nèi)存分配需要調(diào)用頭文件#include<stdlib.h>

malloc函數(shù)

void* malloc (size_t size);

malloc函數(shù)用來(lái)動(dòng)態(tài)開(kāi)辟的, size是開(kāi)辟所需空間的大小,單位:字節(jié)。

并返回起始地址。返回類型是void*,表示我們可以開(kāi)辟任意類型的空間,同時(shí)我們需要強(qiáng)制類型轉(zhuǎn)換成我們開(kāi)辟空間類型的指針,再用指針接收

例如我們開(kāi)辟的是int型的空間,就需要先轉(zhuǎn)換為(int*),再用int*的指針接收

開(kāi)辟float型的空間,就需要先轉(zhuǎn)換為(float*),用于float*的指針接收

int* p = (int*)malloc(sizeof(int) * 10);

重點(diǎn):

1.malloc函數(shù)在開(kāi)辟空間后需要判斷開(kāi)辟空間是否成功,若開(kāi)辟成功會(huì)返回開(kāi)辟好的空間的指針,開(kāi)辟失敗會(huì)返回空指針。

2.malloc函數(shù)并不會(huì)對(duì)開(kāi)辟空間進(jìn)行初始化,空間內(nèi)容為隨機(jī)數(shù)。

下面是關(guān)于malloc函數(shù)的例子,主函數(shù)如下:

主函數(shù)中第一段代碼就是在堆上動(dòng)態(tài)開(kāi)辟10個(gè)int型大小的空間,通過(guò)int*型的指針p去維護(hù)這塊空間,如果空間開(kāi)辟失敗就會(huì)返回NULL,所以我們需要判斷是否開(kāi)辟成功。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{	
	int* p = (int*)malloc(sizeof(int) * 10);
	if (p == NULL)
	{                                     //我們也可以直接eixt(-1)異常退出,或是return;
		printf("%s\n", strerror(errno));  //strerror(errno)是用來(lái)判斷開(kāi)辟失敗的錯(cuò)誤原因                               
		return -1;                        //error是錯(cuò)誤碼
	}                                     //需要調(diào)用最下面的兩個(gè)頭文件
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}
	printf("\n");
	return 0;
}

判斷p為NULL時(shí),也可以直接打印開(kāi)辟失敗,不需要調(diào)用strerror函數(shù),也不用包含那兩個(gè)頭文件

if (p == NULL)
{
	printf("malloc failed\n");
	exit(-1);
}

calloc函數(shù)

void* calloc (size_t num, size_t size);

calloc函數(shù)與malloc類似 ,calloc可以看作malloc+memset

 參數(shù)num是開(kāi)辟空間的元素個(gè)數(shù),參數(shù)size是元素的大小,單位:字節(jié)。

函數(shù)的功能是為 num 個(gè) size大小 的元素開(kāi)辟一塊空間,并且把空間的每個(gè)字節(jié)初始化為0。

calloc函數(shù)與malloc函數(shù)不同點(diǎn)在于:會(huì)將開(kāi)辟的空間都初始化為0(按字節(jié)初始化為0)。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{	
	int* p = (int*)calloc(10, sizeof(int));
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return -1;
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}
	printf("\n");
	return 0;
}

下面看運(yùn)行結(jié)果都為0

realloc函數(shù)

realloc函數(shù)讓動(dòng)態(tài)內(nèi)存管理變得更加靈活,空間不夠時(shí)可以對(duì)動(dòng)態(tài)開(kāi)辟的空間擴(kuò)容

void* realloc(void* ptr, size_t szie);

參數(shù)ptr為需要擴(kuò)充動(dòng)態(tài)內(nèi)存分配的空間的地址

size是 調(diào)整之后新大小,返回參數(shù)為調(diào)整之后的內(nèi)存起始位置。

realloc在調(diào)整內(nèi)存空間的是存在兩種情況:

1.原地?cái)U(kuò)容

在需要擴(kuò)容的空間后有足夠的空間進(jìn)行擴(kuò)容,要擴(kuò)展內(nèi)存就直接原有內(nèi)存之后直接追加空間,原來(lái)空間的數(shù)據(jù)不發(fā)生變化。

2.異地?cái)U(kuò)容

原有空間之后沒(méi)有足夠多的空間時(shí),擴(kuò)展的方法是:在堆空間上另找一個(gè)合適大小 的連續(xù)空間來(lái)使用。這樣函數(shù)返回的是一個(gè)新的內(nèi)存地址。

pc指向的空間的數(shù)據(jù)會(huì)遷移到ptr指向的空間,此時(shí)不需要將pc的空間free,系統(tǒng)會(huì)自動(dòng)釋放。

下圖通過(guò)兩行代碼了解什么是異地?cái)U(kuò)容,可以看到p1和p2的地址發(fā)生了變化

p1的值是0x006b56b8  p2的值是0x006bf4d0,所以擴(kuò)容后的空間地址與原空間地址不同,這就是異地?cái)U(kuò)容

當(dāng)然擴(kuò)容失敗就會(huì)返回NULL,異常退出了

下面是malloc和realloc的聯(lián)合使用,我們擴(kuò)容后要將擴(kuò)容后的空間再次交給原指針去維護(hù)

所以將p=ptr

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
	int* p =(int*) malloc(sizeof(int)*10);
	if (p == NULL)
	{
		printf("malloc faied\n");
		return -1;
	}
	int* ptr = (int*)realloc(p, sizeof(int) * 20);
	if (ptr == NULL)
		return -1;
	p = ptr;
	for (int j = 0; j < 20; j++)
	{
		printf("%d ", p[j]);
	}
 
	printf("\n");
    
    return 0;
}

運(yùn)行結(jié)果可以看到都是隨機(jī)數(shù),所以realloc函數(shù)也不會(huì)初始化

可以看出realloc與malloc相似,都不會(huì)初始化。同時(shí)這也是realloc和malloc的一個(gè)特性,

當(dāng)要擴(kuò)容的對(duì)象為空時(shí),realloc可以當(dāng)作malloc函數(shù)使用。

擴(kuò)充

我們一般動(dòng)態(tài)開(kāi)辟的空間都是結(jié)構(gòu)體,下面簡(jiǎn)單介紹一下開(kāi)辟結(jié)構(gòu)體類型的空間

我們首先定義了一個(gè)結(jié)構(gòu)體類型,里面定義的是int型的數(shù)據(jù)data,還有一個(gè)next型的指針,存放下一節(jié)點(diǎn)的地址,這就是數(shù)據(jù)結(jié)構(gòu)的單鏈表結(jié)構(gòu),不了解的小伙伴可以簡(jiǎn)單看一下

pc指向開(kāi)辟的一個(gè)節(jié)點(diǎn)用,p指向開(kāi)辟的另一個(gè)節(jié)點(diǎn)用,將pc指向的結(jié)構(gòu)體中的next保存p指向節(jié)點(diǎn)的地址

#include <stdio.h>
#include <stdlib.h>
 
typedef struct QueueNode
{
	DataType data;
	struct QueueNode* next;
}QueueNode;
 
int main()
{
	QueueNode* pc = (QueueNode*)malloc(sizeof(QueueNode));
	QueueNode* p = (QueueNode*)malloc(sizeof(QueueNode));
 
	if (pc == NULL && pc == NULL)
	{
		printf("malloc failde\n");
		exit(-1);
	}
	pc->data = 10;
	pc->next = p;
 
	p->data = 20;
	p->next = NULL;
 
	printf("%d %d\n", pc->data, p->data);
	printf("%p %p %p\n", pc->next, p, p->next);
	free(pc);
	free(p);
	pc = p = NULL;
 
	return 0;
}

重點(diǎn):動(dòng)態(tài)開(kāi)辟使用完后,一定要記得free,置空。

了解完上面的內(nèi)容,是不是對(duì)動(dòng)態(tài)分配有了更深的理解。

malloc/calloc/realloc區(qū)別總結(jié)

相同點(diǎn):

1.都是從堆上申請(qǐng)空間

2.都需要對(duì)返回值判空

3.都需要用戶free釋放

4.返回值類型相同(void*)

5.都需要類型轉(zhuǎn)化

6.底層實(shí)現(xiàn)上是一樣的,都需要開(kāi)辟多余的空間,用來(lái)維護(hù)申請(qǐng)的空間

可以輸入以下代碼觀測(cè)內(nèi)存:

#include <stdio.h>
#include <malloc.h>
int main(){
int *p= (int *)malloc(sizeof(int )*10);
return 0;
}

不同點(diǎn):

1.函數(shù)名字不同和參數(shù)類型不同。

2.calloc會(huì)對(duì)申請(qǐng)空間初始化,并且初始化為0,而其他兩個(gè)不會(huì)。

3.malloc申請(qǐng)的空間必須使用memset初始化

4.realloc是對(duì)已經(jīng)存在的空間進(jìn)行調(diào)整,當(dāng)?shù)谝粋€(gè)參數(shù)傳入NULL的時(shí)候和malloc一樣

總結(jié)

到此這篇關(guān)于C語(yǔ)言中動(dòng)態(tài)內(nèi)存分配malloc、calloc和realloc函數(shù)解析的文章就介紹到這了,更多相關(guān)C語(yǔ)言動(dòng)態(tài)內(nèi)存分配函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言中關(guān)于scanf讀取緩存區(qū)的問(wèn)題

    C語(yǔ)言中關(guān)于scanf讀取緩存區(qū)的問(wèn)題

    scanf()函數(shù)是通用終端格式化輸入函數(shù),它從標(biāo)準(zhǔn)輸入設(shè)備(鍵盤) 讀取輸入的信息,接下來(lái)通過(guò)本文給大家介紹C語(yǔ)言中關(guān)于scanf讀取緩存區(qū)的問(wèn)題,需要的朋友一起看看吧
    2021-09-09
  • c++與python實(shí)現(xiàn)二分查找的原理及實(shí)現(xiàn)

    c++與python實(shí)現(xiàn)二分查找的原理及實(shí)現(xiàn)

    本文介紹了c++與python實(shí)現(xiàn)二分查找的原理及實(shí)現(xiàn),二分查找指首先將數(shù)組中間值和目標(biāo)值進(jìn)行比較,如果相等則返回;如果不相等,則選擇中間值左邊的一半或者右邊的一半進(jìn)行比較;不斷重復(fù)直到檢索完畢,下文相關(guān)資料需要的朋友可以參考一下
    2022-03-03
  • 深入分析C++中幾個(gè)最不常用的關(guān)鍵字

    深入分析C++中幾個(gè)最不常用的關(guān)鍵字

    本篇文章是對(duì)C++中幾個(gè)最不常用的關(guān)鍵字進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C語(yǔ)言與C++中內(nèi)存管理詳解

    C語(yǔ)言與C++中內(nèi)存管理詳解

    本章主要介紹C語(yǔ)言與C++的內(nèi)存管理,以C++的內(nèi)存分布作為引入,介紹C++不同于C語(yǔ)言的內(nèi)存管理方式(new?delete對(duì)比?malloc?free),感興趣的朋友來(lái)看看吧
    2022-04-04
  • C語(yǔ)言深入探究函數(shù)的溯源

    C語(yǔ)言深入探究函數(shù)的溯源

    函數(shù)是一組一起執(zhí)行一個(gè)任務(wù)的語(yǔ)句。每個(gè) C 程序都至少有一個(gè)函數(shù),即主函數(shù) main() ,所有簡(jiǎn)單的程序都可以定義其他額外的函數(shù)
    2022-04-04
  • C++深入講解new與deleted關(guān)鍵字的使用

    C++深入講解new與deleted關(guān)鍵字的使用

    這篇文章主要介紹了C++中new與deleted關(guān)鍵字的使用,new在動(dòng)態(tài)內(nèi)存中為對(duì)象分配空間并返回一個(gè)指向該對(duì)象的指針;delete接受一個(gè)動(dòng)態(tài)對(duì)象的指針, 銷毀該對(duì)象, 并釋放與之關(guān)聯(lián)的內(nèi)存
    2022-05-05
  • C語(yǔ)言中枚舉與指針的實(shí)例詳解

    C語(yǔ)言中枚舉與指針的實(shí)例詳解

    這篇文章主要介紹了 C語(yǔ)言中枚舉與指針的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文大家能夠掌握枚舉與指針的知識(shí),需要的朋友可以參考下
    2017-09-09
  • C/C++淺析鄰接表拓?fù)渑判蛩惴ǖ膶?shí)現(xiàn)

    C/C++淺析鄰接表拓?fù)渑判蛩惴ǖ膶?shí)現(xiàn)

    這篇文章主要介紹了C/C++對(duì)于鄰接表拓?fù)渑判蛩惴ǖ膶?shí)現(xiàn),鄰接表是圖的一種鏈?zhǔn)酱鎯?chǔ)方法,其數(shù)據(jù)結(jié)構(gòu)包括兩部分:節(jié)點(diǎn)和鄰接點(diǎn)
    2022-07-07
  • 如何將編譯過(guò)的C++庫(kù)迅速部署在Visual?Studio新項(xiàng)目中

    如何將編譯過(guò)的C++庫(kù)迅速部署在Visual?Studio新項(xiàng)目中

    本文介紹在Visual?Studio中,通過(guò)屬性表,使得一個(gè)新建解決方案中的項(xiàng)目可以快速配置已有解決方案的項(xiàng)目中各類已編譯好的C++第三方庫(kù)的方法,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • C++二維數(shù)組中的查找算法示例

    C++二維數(shù)組中的查找算法示例

    這篇文章主要介紹了C++二維數(shù)組中的查找算法,結(jié)合實(shí)例形式分析了C++二維數(shù)組進(jìn)行查找的原理與具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-05-05

最新評(píng)論

九江县| 桑植县| 潼南县| 元氏县| 怀宁县| 通渭县| 宁波市| 甘洛县| 和田市| 普兰县| 精河县| 惠水县| 清涧县| 平顶山市| 桑日县| 江永县| 凌云县| 蕲春县| 镇江市| 包头市| 昭苏县| 陆河县| 青浦区| 花莲县| 莱州市| 简阳市| 延寿县| 萨迦县| 克什克腾旗| 旬邑县| 光泽县| 察隅县| 手游| 南城县| 靖边县| 河北省| 太和县| 益阳市| 白玉县| 上思县| 喜德县|