欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語(yǔ)言動(dòng)態(tài)內(nèi)存分配圖文講解

 更新時(shí)間:2023年01月17日 11:12:00   作者:戊子仲秋  
給數(shù)組分配多大的空間?你是否和初學(xué)C時(shí)的我一樣,有過(guò)這樣的疑問(wèn)。這一期就來(lái)聊一聊動(dòng)態(tài)內(nèi)存的分配,讀完這篇文章,你可能對(duì)內(nèi)存的分配有一個(gè)更好的理解

思維導(dǎo)圖

1.為什么存在動(dòng)態(tài)內(nèi)存分配

我們現(xiàn)在學(xué)習(xí)了一些內(nèi)存開(kāi)辟的方式:

int main()
{
	int i;//在內(nèi)存棧區(qū)開(kāi)辟4個(gè)字節(jié)空間
	char arr[5];//在??臻g上開(kāi)辟5個(gè)字節(jié)的連續(xù)空間
	return 0;
}

但是,這樣開(kāi)辟的內(nèi)存是靜態(tài)的,固定的:

1. 空間開(kāi)辟大小是固定的。

2. 數(shù)組在申明的時(shí)候,必須指定數(shù)組的長(zhǎng)度,它所需要的內(nèi)存在編譯時(shí)分配。

如果想要在編譯過(guò)程中開(kāi)辟空間,就需要用到動(dòng)態(tài)內(nèi)存。

2.動(dòng)態(tài)內(nèi)存函數(shù)的介紹

2.1 malloc

void* malloc (size_t size)

2.2 free

void free (void* ptr)

例:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	//申請(qǐng)40給字節(jié),用來(lái)存放10個(gè)整形
	int* p = (int*)malloc(40);//malloc申請(qǐng)的空間不會(huì)初始化
	if (p == NULL)            //直接返回起始地址
	{
		perror("malloc");//如果空間開(kāi)辟失敗要報(bào)錯(cuò)并返回
		return 1;
	}
	//使用空間
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", *(p + i));
	}
	//釋放申請(qǐng)的內(nèi)存
	free(p);
	p = NULL;
	return 0;
}

輸出:

輸出:
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451
-842150451

malloc不會(huì)自己初始化,所以打印隨機(jī)值。

例:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	//申請(qǐng)40給字節(jié),用來(lái)存放10個(gè)整形
	int* p = (int*)malloc(40);//malloc申請(qǐng)的空間沒(méi)有初始化
	if (p == NULL)            //直接返回起始地址
	{
		perror("malloc");//如果空間開(kāi)辟失敗要報(bào)錯(cuò)并返回
		return 1;
	}
	//使用空間
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i + 1;//初始化賦值
		printf("%d ", *(p + i));
	}
	//釋放申請(qǐng)的內(nèi)存
	free(p);
	p = NULL;
	return 0;
}

輸出:

輸出:1 2 3 4 5 6 7 8 9 10

2.3 calloc

void* calloc (size_t num, size_t size)

例:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int* p = (int*)calloc(10, sizeof(int));//10是要初始化的個(gè)數(shù),sizeof(int)是每個(gè)的大小
	if (NULL == p)
	{
		perror("calloc");//判斷內(nèi)存是否申請(qǐng)成功
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));//calloc申請(qǐng)空間后,會(huì)把空間初始化成0
	}                                              //再返回起始地址
	//釋放
	free(p);
	p = NULL;
}

輸出:

輸出:0 0 0 0 0 0 0 0 0 0

2.4 realloc

void* realloc (void* ptr, size_t size)

realloc函數(shù)可以追加更多動(dòng)態(tài)內(nèi)存。

例:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int* p = (int*)malloc(5 * sizeof(int));//開(kāi)辟一段動(dòng)態(tài)內(nèi)存20個(gè)字節(jié)
	if (NULL == p)
	{
		perror("malloc");//檢查是否創(chuàng)建成功
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		*(p + i) = i + 1;
	}
	//不夠用,增加5個(gè)整形的空間
	int* ptr = (int*)realloc(p, 10 * sizeof(int));//這里是開(kāi)辟到40個(gè)字節(jié)
	//realloc函數(shù)開(kāi)辟內(nèi)存空間有兩種情況:
	//1.原內(nèi)存塊后面空間足夠,在原內(nèi)存塊后面追加內(nèi)存
	//2.原內(nèi)存塊后面空間不夠,另外找一片區(qū)域開(kāi)辟內(nèi)存,將原內(nèi)存塊釋放
	if (ptr != NULL)
	{
		p = ptr;//為什么不直接用p接收?
		//如果內(nèi)存追加失敗,直接用p接收的話(huà),原本已經(jīng)開(kāi)辟的動(dòng)態(tài)內(nèi)存空間就會(huì)被覆蓋
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
	//釋放
	free(p);
	p = NULL;
	return 0;
}

輸出:

輸出:1 2 3 4 5 -842150451 -842150451 -842150451 -842150451 -842150451

3.常見(jiàn)的動(dòng)態(tài)內(nèi)存錯(cuò)誤

例1:

開(kāi)辟動(dòng)態(tài)內(nèi)存記得要判斷,最后釋放內(nèi)存。

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int* p = (int*)malloc(100);
	//內(nèi)存開(kāi)辟后沒(méi)有判斷是否開(kāi)辟成功
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = 0;//危險(xiǎn)代碼,我們無(wú)法知道是否存在非法訪(fǎng)問(wèn)
	}
	//并且最后也沒(méi)有將開(kāi)辟的內(nèi)存還給操作系統(tǒng)
	return 0;
}

例2:

動(dòng)態(tài)內(nèi)存開(kāi)辟了多少就用多少,小心越界訪(fǎng)問(wèn)。

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int* p = (int*)malloc(100);//開(kāi)辟了100字節(jié)空間
	//判斷
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 100; i++)//造成越界訪(fǎng)問(wèn)
	{
		*(p + i) = 0;//一個(gè)整形4個(gè)字節(jié)
	}
	//釋放
	free(p);
	p = NULL;
	return 0;
}

例3:

不要亂釋放其他內(nèi)存空間。

int main()
{
	int a = 10;
	int* p = &a;
	//你沒(méi)有權(quán)限亂釋放其他的內(nèi)存空間
	free(p);//不能對(duì)棧區(qū)的內(nèi)存釋放
	return 0;
}

例4:

不要多次釋放內(nèi)存空間。

#include <stdio.h>
#include <stdlib.h>
int main()
{
	//開(kāi)辟空間
	int* p = (int*)malloc(100);
	//判斷
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 25; i++)
	{
		*p = i;
		p++;//p指針不斷往后移動(dòng)
	}
	//釋放的時(shí)候指針應(yīng)該指向起始地址,否則程序又會(huì)出錯(cuò)
	free(p);
	p = NULL;
	return 0;
}

例5:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	//創(chuàng)建
	int* p = (int*)malloc(100);
	//判斷
	if (p == NULL)
	{
		return 1;
	}
	//釋放
	free(p);
	free(p);//已經(jīng)釋放了,重復(fù)釋放會(huì)導(dǎo)致程序出錯(cuò)
	return 0;
}

這就要說(shuō)到最后置為空指針的好處了:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	//創(chuàng)建
	int* p = (int*)malloc(100);
	//判斷
	if (p == NULL)
	{
		return 1;
	}
	//釋放
	free(p);
	p = NULL;//置為空指針后程序就不會(huì)崩潰了
	free(p);//p為空指針時(shí),程序不會(huì)報(bào)錯(cuò)
	return 0;
}

例5:

在實(shí)現(xiàn)函數(shù)時(shí)開(kāi)辟了動(dòng)態(tài)內(nèi)存要記得及時(shí)釋放或者返回地址,

不然就再也找不到那段內(nèi)存空間了,最后導(dǎo)致內(nèi)存泄漏。

#include <stdio.h>
#include <stdlib.h>
void test()
{
	int* p = (int*)malloc(100);
	//忘記釋放
}//出了函數(shù)就找不到了,因?yàn)樽兞縫被銷(xiāo)毀了
//造成內(nèi)存泄漏
int main()
{
	test();
	return 0;
}
 

例6:

這道題也是類(lèi)似的:

#include <stdio.h>
#include <stdlib.h>
void test()
{
	int* p = (int*)malloc(100);
	if (p == NULL)
	{
		return;
	}
	//使用
	if (1)
		return;//出問(wèn)題//內(nèi)存泄漏
	//釋放
	free(p);
	p = NULL;
}
int main()
{
	test();
	return 0;
}

要小心出現(xiàn)內(nèi)存泄漏,記得釋放空間。

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

相關(guān)文章

  • C/C++使用C語(yǔ)言實(shí)現(xiàn)多態(tài)

    C/C++使用C語(yǔ)言實(shí)現(xiàn)多態(tài)

    這篇文章主要介紹了C/C++多態(tài)的實(shí)現(xiàn)機(jī)制理解的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下,希望能給你帶來(lái)幫助
    2021-08-08
  • STL 的string類(lèi)怎么啦

    STL 的string類(lèi)怎么啦

    在我們研究string類(lèi)犯了什么毛病之前,還讓我先說(shuō)一下如何了解一個(gè)C++的類(lèi)。我們要了解一個(gè)C++的類(lèi),一般來(lái)說(shuō),要從三個(gè)方面入手
    2013-11-11
  • C/C++預(yù)處理淺析使用形式

    C/C++預(yù)處理淺析使用形式

    預(yù)處理是指在進(jìn)行編譯的詞法掃描和語(yǔ)法分析之前所作的工作。預(yù)處理指令指示在程序正式編譯前就由編譯器進(jìn)行的操作,可放在程序中任何位置。處理完畢自動(dòng)進(jìn)入對(duì)源程序的編譯。C/C++中的預(yù)處理主要包含三種:文件包含、宏定義、條件編譯
    2022-09-09
  • C++移動(dòng)語(yǔ)義詳細(xì)介紹使用

    C++移動(dòng)語(yǔ)義詳細(xì)介紹使用

    首先,移動(dòng)語(yǔ)義和完美轉(zhuǎn)發(fā)這兩個(gè)概念是在C++的模板編程的基礎(chǔ)上,新增的特性,主要是配合模板來(lái)使用。本篇會(huì)從C++的值類(lèi)型,到移動(dòng)拷貝與移動(dòng)賦值來(lái)理解移動(dòng)語(yǔ)義與完美轉(zhuǎn)發(fā)
    2023-01-01
  • C語(yǔ)言實(shí)現(xiàn)字母大小寫(xiě)轉(zhuǎn)換的方法

    C語(yǔ)言實(shí)現(xiàn)字母大小寫(xiě)轉(zhuǎn)換的方法

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)字母大小寫(xiě)轉(zhuǎn)換的方法,涉及C語(yǔ)言字符串的遍歷與轉(zhuǎn)換技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下
    2015-07-07
  • VC小技巧匯總之對(duì)話(huà)框技巧

    VC小技巧匯總之對(duì)話(huà)框技巧

    這篇文章主要介紹了VC小技巧匯總之對(duì)話(huà)框技巧,非常實(shí)用!對(duì)于進(jìn)行VC開(kāi)發(fā)有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-07-07
  • C語(yǔ)言清楚了解指針的使用

    C語(yǔ)言清楚了解指針的使用

    C語(yǔ)言這門(mén)課程在計(jì)算機(jī)的基礎(chǔ)教學(xué)中一直占有比較重要的地位,然而要想突破C語(yǔ)言的學(xué)習(xí),對(duì)指針的掌握是非常重要的,本文將具體針對(duì)指針的基礎(chǔ)做詳盡的介紹
    2022-06-06
  • C++運(yùn)算符重載圖文詳解

    C++運(yùn)算符重載圖文詳解

    運(yùn)算符重載的方法是定義一個(gè)重載運(yùn)算符的函數(shù),在需要執(zhí)行被重載的運(yùn)算符時(shí),系統(tǒng)就自動(dòng)調(diào)用該函數(shù),以實(shí)現(xiàn)相應(yīng)的運(yùn)算。也就是說(shuō),運(yùn)算符重載是通過(guò)定義函數(shù)實(shí)現(xiàn)的
    2021-09-09
  • C++設(shè)計(jì)模式之適配器模式(Adapter)

    C++設(shè)計(jì)模式之適配器模式(Adapter)

    這篇文章主要為大家詳細(xì)介紹了C++設(shè)計(jì)模式之適配器模式Adapter,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 用C語(yǔ)言如何打印一個(gè)等腰三角形

    用C語(yǔ)言如何打印一個(gè)等腰三角形

    這篇文章主要介紹了用C語(yǔ)言如何打印一個(gè)等腰三角形,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11

最新評(píng)論