亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

前言

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

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

free函數(shù)

free函數(shù)是專門用來對動態(tài)開辟內(nèi)存的回收和釋放的。當我們不需要再使用動態(tài)開辟的空間時,一定要free釋放空間,因為是在堆上開辟的空間,所以不會隨著出了作用域而銷毀,需要我們free釋放,避免內(nèi)存泄漏,并置空(將指針置為NULL),避免形成野指針。

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

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

void free (void* ptr);

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

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

下面我們來實現(xiàn)一下。

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

malloc函數(shù)

void* malloc (size_t size);

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

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

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

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

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

重點:

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

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

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

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

#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)是用來判斷開辟失敗的錯誤原因                               
		return -1;                        //error是錯誤碼
	}                                     //需要調(diào)用最下面的兩個頭文件
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}
	printf("\n");
	return 0;
}

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

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是開辟空間的元素個數(shù),參數(shù)size是元素的大小,單位:字節(jié)。

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

calloc函數(shù)與malloc函數(shù)不同點在于:會將開辟的空間都初始化為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;
}

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

realloc函數(shù)

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

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

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

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

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

1.原地擴容

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

2.異地擴容

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

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

下圖通過兩行代碼了解什么是異地擴容,可以看到p1和p2的地址發(fā)生了變化

p1的值是0x006b56b8  p2的值是0x006bf4d0,所以擴容后的空間地址與原空間地址不同,這就是異地擴容

當然擴容失敗就會返回NULL,異常退出了

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

所以將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;
}

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

可以看出realloc與malloc相似,都不會初始化。同時這也是realloc和malloc的一個特性,

當要擴容的對象為空時,realloc可以當作malloc函數(shù)使用。

擴充

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

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

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

#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;
}

重點:動態(tài)開辟使用完后,一定要記得free,置空。

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

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

相同點:

1.都是從堆上申請空間

2.都需要對返回值判空

3.都需要用戶free釋放

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

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

6.底層實現(xiàn)上是一樣的,都需要開辟多余的空間,用來維護申請的空間

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

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

不同點:

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

2.calloc會對申請空間初始化,并且初始化為0,而其他兩個不會。

3.malloc申請的空間必須使用memset初始化

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

總結(jié)

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

相關(guān)文章

  • C語言中字符串庫函數(shù)的實現(xiàn)及模擬

    C語言中字符串庫函數(shù)的實現(xiàn)及模擬

    C語言中有很多數(shù)據(jù)類型,比如int(整數(shù)類型)、char(字符類型)、以及浮點型的double(雙精度)等。但是有一點就是我們發(fā)現(xiàn)這里并沒有提到我們常見的有關(guān)字符串的類型。本文為大家介紹了C語言中字符串庫函數(shù)的實現(xiàn)及模擬,需要的可以參考一下
    2022-11-11
  • 詳解C/C++中const限定符總結(jié)

    詳解C/C++中const限定符總結(jié)

    const是一種限定符,被const所限定的變量其值不可以被改變。。這篇文章主要介紹了C/C++中const限定符總結(jié),通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • 深入解析Radix Sort基數(shù)排序算法思想及C語言實現(xiàn)示例

    深入解析Radix Sort基數(shù)排序算法思想及C語言實現(xiàn)示例

    基數(shù)排序和桶排序、計數(shù)排序共同是三種最常用的線性排序算法,這里我們就來深入解析Radix Sort基數(shù)排序算法思想及C語言實現(xiàn)示例,需要的朋友可以參考下
    2016-07-07
  • C語言如何輸出中文

    C語言如何輸出中文

    這篇文章主要介紹了C語言如何輸出中文問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • C++知識點之成員函數(shù)中const的用法

    C++知識點之成員函數(shù)中const的用法

    這篇文章主要介紹了C++知識點之成員函數(shù)中const的用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C++中this指針理解及作用

    C++中this指針理解及作用

    這篇文章主要介紹了C++中this指針理解及作用,文章通過舉例展開相關(guān)詳細內(nèi)容,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-05-05
  • C++語言中std::array的用法小結(jié)(神器用法)

    C++語言中std::array的用法小結(jié)(神器用法)

    這篇文章主要介紹了C++語言中std::array的用法小結(jié),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • C++實現(xiàn)萬年歷小功能

    C++實現(xiàn)萬年歷小功能

    這篇文章主要為大家詳細介紹了C++實現(xiàn)萬年歷小功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C++事件處理中的__hook與__unhook用法詳解

    C++事件處理中的__hook與__unhook用法詳解

    這篇文章主要介紹了C++事件處理中__hook與__unhook的用法,C++中的COM類主要支持事件處理,需要的朋友可以參考下
    2016-01-01
  • C語言如何實現(xiàn)BOOL類型

    C語言如何實現(xiàn)BOOL類型

    這篇文章主要介紹了C語言如何實現(xiàn)BOOL類型問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評論