??【數(shù)據(jù)結(jié)構(gòu)與算法】專(zhuān)題正在持續(xù)更新中,各種數(shù)據(jù)結(jié)構(gòu)的創(chuàng)建原理與運(yùn)用?,經(jīng)典算法的解析?都在這兒,歡迎大家前往訂閱本專(zhuān)題,獲取更多詳細(xì)信息哦??????
??本系列專(zhuān)欄 - ?數(shù)據(jù)結(jié)構(gòu)與算法_勾欄聽(tīng)曲_0
??歡迎大家 ??? ?點(diǎn)贊?? ?評(píng)論?? ?收藏??
??個(gè)人主頁(yè) - 勾欄聽(tīng)曲_0的博客??
??希望本文能對(duì)你有所幫助,如有不足請(qǐng)指正,共同進(jìn)步吧??
??善治病者,必醫(yī)其受病之處;善救弊者,必塞其起弊之源。??
目錄
動(dòng)態(tài)分配
意義
動(dòng)態(tài)分配與靜態(tài)分配內(nèi)存的異同于優(yōu)缺點(diǎn)
何時(shí)需要?jiǎng)討B(tài)分配
動(dòng)態(tài)分配函數(shù)
malloc
calloc
realloc
三者的異同
數(shù)組中的動(dòng)態(tài)分配
結(jié)構(gòu)體中的動(dòng)態(tài)分配
鏈表中的動(dòng)態(tài)分配
動(dòng)態(tài)分配
意義
????????在計(jì)算機(jī)科學(xué)中,?動(dòng)態(tài)內(nèi)存分配(Dynamic memory allocation)又稱(chēng)為堆內(nèi)存分配,是指計(jì)算機(jī)程序在運(yùn)行期中分配使用內(nèi)存。它可以當(dāng)成是一種分配有限內(nèi)存資源所有權(quán)的方法。
????????動(dòng)態(tài)分配的內(nèi)存在被程序員明確釋放或垃圾回收之前一直有效。與靜態(tài)內(nèi)存分配的區(qū)別在于沒(méi)有一個(gè)固定的生存期。這樣被分配的對(duì)象稱(chēng)之為有一個(gè)“動(dòng)態(tài)生存期”。
????????動(dòng)態(tài)分配的意義是為了讓程序能夠根據(jù)運(yùn)行時(shí)的需要,靈活地分配和釋放內(nèi)存空間,以提高內(nèi)存利用率和程序的功能性。動(dòng)態(tài)分配可以解決以下問(wèn)題:
????????當(dāng)程序運(yùn)行時(shí),無(wú)法確定變量(如數(shù)組、結(jié)構(gòu)體、鏈表等)的大小或個(gè)數(shù)時(shí),靜態(tài)分配的內(nèi)存空間可能不夠或浪費(fèi),而動(dòng)態(tài)分配可以根據(jù)實(shí)際情況分配合適的空間。
????????當(dāng)程序運(yùn)行時(shí),需要頻繁地創(chuàng)建和銷(xiāo)毀變量時(shí),靜態(tài)分配的內(nèi)存空間可能造成內(nèi)存碎片或不足,而動(dòng)態(tài)分配可以及時(shí)釋放不用的空間,避免內(nèi)存泄漏。
????????當(dāng)程序運(yùn)行時(shí),需要將變量的生命周期延長(zhǎng)到函數(shù)調(diào)用結(jié)束后時(shí),靜態(tài)分配的局部變量會(huì)在函數(shù)返回時(shí)被銷(xiāo)毀,而動(dòng)態(tài)分配的變量可以保持有效,直到被釋放。
動(dòng)態(tài)分配與靜態(tài)分配內(nèi)存的異同于優(yōu)缺點(diǎn)
????????動(dòng)態(tài)分配與靜態(tài)分配的異同與優(yōu)缺點(diǎn)如下:
????????異:
????????????????靜態(tài)分配是編譯器完成的,比如局部變量的分配。動(dòng)態(tài)分配是程序運(yùn)行時(shí)由程序員通過(guò)函數(shù)(如malloc、calloc等)進(jìn)行分配。
????????????????靜態(tài)分配的內(nèi)存空間是在棧上分配的,生命周期和作用域受函數(shù)限制。動(dòng)態(tài)分配的內(nèi)存空間是在堆上分配的,生命周期和作用域由程序員控制。
????????????????靜態(tài)分配的內(nèi)存空間是連續(xù)的,大小和個(gè)數(shù)在編譯時(shí)確定。動(dòng)態(tài)分配的內(nèi)存空間是不連續(xù)的,大小和個(gè)數(shù)在運(yùn)行時(shí)確定。
????????同:
????????????????靜態(tài)分配和動(dòng)態(tài)分配都是為了給變量或數(shù)據(jù)結(jié)構(gòu)分配內(nèi)存空間,以便存儲(chǔ)數(shù)據(jù)和信息1。
靜態(tài)分配和動(dòng)態(tài)分配都需要遵循一些規(guī)則和約束,以保證程序的正確性和安全性。
????????優(yōu)缺點(diǎn):
????????????????靜態(tài)分配的優(yōu)點(diǎn)是簡(jiǎn)單、快速、安全,不需要手動(dòng)管理內(nèi)存空間。缺點(diǎn)是浪費(fèi)內(nèi)存空間,不能適應(yīng)程序運(yùn)行時(shí)的變化。
????????????????動(dòng)態(tài)分配的優(yōu)點(diǎn)是節(jié)省內(nèi)存空間,能適應(yīng)程序運(yùn)行時(shí)的變化,能創(chuàng)建復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。缺點(diǎn)是復(fù)雜、慢速、危險(xiǎn),需要手動(dòng)管理內(nèi)存空間。
何時(shí)需要?jiǎng)討B(tài)分配
????????動(dòng)態(tài)分配內(nèi)存的目的是為了節(jié)省內(nèi)存空間,提高內(nèi)存利用率,以及適應(yīng)程序運(yùn)行時(shí)的不確定性1。一般來(lái)說(shuō),以下情況需要?jiǎng)討B(tài)分配內(nèi)存:
????????????????當(dāng)程序運(yùn)行時(shí),無(wú)法確定變量(如數(shù)組、結(jié)構(gòu)體、鏈表等)的大小或個(gè)數(shù)時(shí),需要?jiǎng)討B(tài)分配內(nèi)存來(lái)根據(jù)實(shí)際情況分配合適的空間。
????????????????當(dāng)程序運(yùn)行時(shí),需要頻繁地創(chuàng)建和銷(xiāo)毀變量時(shí),需要?jiǎng)討B(tài)分配內(nèi)存來(lái)避免靜態(tài)分配的內(nèi)存浪費(fèi)或不足。
????????????????當(dāng)程序運(yùn)行時(shí),需要將變量的生命周期延長(zhǎng)到函數(shù)調(diào)用結(jié)束后時(shí),需要?jiǎng)討B(tài)分配內(nèi)存來(lái)保持變量的有效性。
但是需要注意的是,動(dòng)態(tài)分配由他的好處,同時(shí)也有一些弊端:
動(dòng)態(tài)分配內(nèi)存的好處和壞處如下:
????????好處:
????????????????可以根據(jù)程序運(yùn)行時(shí)的需要,靈活地分配和釋放內(nèi)存空間,提高內(nèi)存利用率。
????????????????可以創(chuàng)建一些復(fù)雜的數(shù)據(jù)結(jié)構(gòu),如鏈表、樹(shù)、圖等,實(shí)現(xiàn)更多的功能。
????????????????可以將變量的生命周期延長(zhǎng)到函數(shù)調(diào)用結(jié)束后,避免局部變量的作用域限制。
????????壞處:
????????????????需要手動(dòng)管理內(nèi)存空間,容易出現(xiàn)內(nèi)存泄漏、內(nèi)存碎片、內(nèi)存溢出等問(wèn)題。
????????????????動(dòng)態(tài)分配的內(nèi)存空間通常不連續(xù),可能影響程序的性能和效率。
????????????????動(dòng)態(tài)分配的內(nèi)存空間可能被其他程序或進(jìn)程占用或修改,導(dǎo)致程序出錯(cuò)或崩潰
動(dòng)態(tài)分配函數(shù)
malloc
? ? ? ? 頭文件:
#include <stdlib.h>
? ? ? ? 語(yǔ)法格式:
void *malloc(size_t size);
? ? ? ? 用法舉例:
#include <stdlib.h>
int main() {
int *ptr;
int n;
// 動(dòng)態(tài)分配內(nèi)存空間
ptr = (int*) malloc(sizeof(int) * n);
// 輸出動(dòng)態(tài)分配的內(nèi)存空間大小
printf("Dynamically allocated memory size: %d\n", n);
// 輸出動(dòng)態(tài)分配的內(nèi)存空間地址
printf("Dynamically allocated memory address: %p\n", ptr);
// 輸出動(dòng)態(tài)分配的內(nèi)存空間指針
printf("Dynamically allocated memory pointer: %p\n", ptr);
// 釋放動(dòng)態(tài)分配的內(nèi)存空間
free(ptr);
return 0;
}
calloc
? ? ? ? 頭文件:
#include <stdlib.h>
? ? ? ? 語(yǔ)法格式:
????????????????其中,num
?表示要分配的元素個(gè)數(shù),size
?表示每個(gè)元素的大小。
void* calloc(size_t num, size_t size);
? ? ? ? 用法舉例:
????????????????在這個(gè)例子中,calloc
?函數(shù)接受兩個(gè)參數(shù),num
?表示要分配的元素個(gè)數(shù),size
?表示每個(gè)元素的大小。函數(shù)返回一個(gè)指向分配起始地址的指針,如果分配不成功,則返回?NULL
。
其中,num 表示要分配的元素個(gè)數(shù),size 表示每個(gè)元素的大小。
? ? ? ? 注意:
?????????????????calloc
?函數(shù)在分配內(nèi)存時(shí)會(huì)先檢查分配的內(nèi)存大小是否足夠,如果不足,則會(huì)拋出?malloc
?函數(shù)的?malloc_error
?異常。因此,在使用?calloc
?函數(shù)時(shí),需要確保分配的內(nèi)存大小足夠,否則可能會(huì)導(dǎo)致程序崩潰或產(chǎn)生不可預(yù)測(cè)的行為。
realloc
? ? ? ? 頭文件:
#include <malloc .h>
? ? ? ? 語(yǔ)法格式:
????????????????其中,ptr
?是要重新分配內(nèi)存空間的指針,size
?是要分配的內(nèi)存塊的大小。realloc()
?函數(shù)會(huì)在程序運(yùn)行時(shí)動(dòng)態(tài)計(jì)算需要分配的內(nèi)存大小,并返回一個(gè)指向動(dòng)態(tài)分配的內(nèi)存塊的指針。如果在分配內(nèi)存時(shí)發(fā)生錯(cuò)誤,realloc()
?函數(shù)將返回一個(gè)空指針。
void *realloc(void *ptr, size_t size);
三者的異同
相似之處:
-
malloc
和calloc
都可以用于分配動(dòng)態(tài)內(nèi)存空間,并且都需要傳入兩個(gè)參數(shù),第一個(gè)參數(shù)是要分配的元素個(gè)數(shù),第二個(gè)參數(shù)是每個(gè)元素的大小。 -
malloc
和calloc
都會(huì)將分配的內(nèi)存空間初始化為0,如果分配的內(nèi)存原來(lái)已經(jīng)被分配過(guò),則其中可能會(huì)遺留有各種各樣的數(shù)據(jù)。 -
malloc
和calloc
都可以用于分配指定大小的內(nèi)存空間,并且返回類(lèi)型都是void*
。
不同之處:
-
malloc
是從系統(tǒng)堆上分配內(nèi)存的,而calloc
和realloc
都是在程序運(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存空間的。 -
malloc
返回的是指向動(dòng)態(tài)分配內(nèi)存空間的指針,而calloc
和realloc
返回的是指向分配的內(nèi)存空間的指針。 -
malloc
和calloc
都可以用于擴(kuò)大或縮小分配的內(nèi)存空間,而realloc
只能用于擴(kuò)大分配的內(nèi)存空間。 -
malloc
和calloc
的參數(shù)類(lèi)型不同,malloc
接受的是unsigned int
類(lèi)型的參數(shù),而calloc
和realloc
接受的是size_t
類(lèi)型的參數(shù)。 -
malloc
和calloc
都需要對(duì)返回值進(jìn)行判空,而realloc
不需要。 -
malloc
是一個(gè)標(biāo)準(zhǔn)庫(kù)函數(shù),而calloc
、realloc
和realloc
都是第三方庫(kù)函數(shù)。
數(shù)組中的動(dòng)態(tài)分配
- 聲明一個(gè)指針或指向指針的指針,作為動(dòng)態(tài)數(shù)組的起始地址。
- 使用 malloc() 或 calloc() 函數(shù)為數(shù)組分配內(nèi)存空間,根據(jù)數(shù)組的維數(shù)和元素類(lèi)型確定所需的字節(jié)數(shù)。
- 使用循環(huán)或其他方式來(lái)為數(shù)組中的每個(gè)元素進(jìn)行賦值和訪問(wèn),注意使用下標(biāo)或指針運(yùn)算符。
- 使用 free() 函數(shù)釋放數(shù)組所占用的內(nèi)存空間,避免內(nèi)存泄漏。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *array = NULL; // 聲明一個(gè)整型指針
int len = 10; // 數(shù)組長(zhǎng)度
array = (int *)malloc(len * sizeof(int)); // 為數(shù)組分配內(nèi)存空間
if (array == NULL) // 檢查是否分配成功
{
printf("動(dòng)態(tài)申請(qǐng)內(nèi)存失?。n");
exit(1);
}
for (int i = 0; i < len; i++) // 為數(shù)組賦值
{
array[i] = i + 1;
}
for (int i = 0; i < len; i++) // 打印數(shù)組元素的值和地址
{
printf("array[%d] = %d, &array[%d] = %p\n", i, array[i], i, &array[i]);
}
free(array); // 釋放數(shù)組內(nèi)存
return 0;
}
結(jié)構(gòu)體中的動(dòng)態(tài)分配
????????在上面的代碼中,我們定義了一個(gè)Point
結(jié)構(gòu)體,它包含兩個(gè)整型變量x
和y
。然后,我們使用malloc
函數(shù)動(dòng)態(tài)分配了一個(gè)大小為2
的Point
類(lèi)型的內(nèi)存空間,并將其地址賦值給指針變量p.z
。最后,我們輸出了動(dòng)態(tài)分配的內(nèi)存空間的大小、地址和指針。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-426761.html
#include <stdio.h>
typedef struct {
int x;
int y;
} Point;
int main() {
Point p;
p.x = 10;
p.y = 20;
// 動(dòng)態(tài)分配內(nèi)存空間
p.z = (Point*) malloc(sizeof(Point) * 2);
// 輸出動(dòng)態(tài)分配的內(nèi)存空間大小
printf("Dynamically allocated memory size: %d\n", sizeof(Point) * 2);
// 輸出動(dòng)態(tài)分配的內(nèi)存空間地址
printf("Dynamically allocated memory address: %p\n", p.z);
// 輸出動(dòng)態(tài)分配的內(nèi)存空間指針
printf("Dynamically allocated memory pointer: %p\n", p.z);
// 釋放動(dòng)態(tài)分配的內(nèi)存空間
free(p.z);
return 0;
}
鏈表中的動(dòng)態(tài)分配
????????在上面的代碼中,我們定義了一個(gè)Node
結(jié)構(gòu)體,它包含一個(gè)整型變量data
和一個(gè)指向下一個(gè)節(jié)點(diǎn)的指針next
。然后,我們使用createNode
函數(shù)動(dòng)態(tài)分配了一個(gè)大小為2
的Node
類(lèi)型的內(nèi)存空間,并將其地址賦值給指針變量p.z
。最后,我們輸出了動(dòng)態(tài)分配的內(nèi)存空間的大小、地址和指針。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-426761.html
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} Node;
Node* createNode(int data) {
Node* newNode = (Node*) malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
void printList(Node* head) {
while (head != NULL) {
printf("%d ", head->data);
head = head->next;
}
printf("\n");
}
int main() {
Node* head = createNode(1);
head->next = createNode(2);
head->next->next = createNode(3);
head->next->next->next = createNode(4);
printList(head);
// 動(dòng)態(tài)分配內(nèi)存空間
head->next->next->next = createNode(5);
printList(head);
return 0;
}
到了這里,關(guān)于如何實(shí)現(xiàn)動(dòng)態(tài)分配,malloc,realloc,calloc的使用方法,數(shù)組,鏈表,結(jié)構(gòu)體實(shí)現(xiàn)動(dòng)態(tài)分配(含代碼實(shí)現(xiàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!