文章目錄
在C語言中,編寫程序的時候不能確定內存的大小,希望程序在運行的過程中根據數據量的大小動態的分配內存。動態內存管理,就是指在程序運行過程中動態的申請和釋放內存空間。
C語言允許程序動態管理內存,需要時隨時開闢,不需要時隨時釋放。內存的動態管理是通過調用庫函數來實現的,主要有malloc和free函數。
一、相關的庫函數
1、malloc 函數
函數的原型:
void *malloc(unsigned int size);
malloc的作用是向系統申請一塊大小爲size的連續內存空間,如果申請失敗,函數返回0,如果申請成功,返回成功分配內存塊的起始地址。
例如:
malloc(100); // 申請 100 個字節的臨時分配域,返回值爲其第一個字節的地址
malloc的返回值的地址的基類型爲void,即不指向任何類型的數據,只提供一個地址,程序中需要定義一個指針來指向動態分配的內存地址。
例如:
int *pi=malloc(sizeof(int));
2、free 函數
函數的原型:
void free(void *p);
free的作用是釋放指針p指向的動態內存空間,p是調用malloc函數時返回的地址,free函數無返回值。
例如:
free(pi); // 釋放指針變量pi指向的已分配的動態空間
示例(book107.c)
/*
* 程序名:book107.c,此程序用於演示C程序動態內存管理。
* 作者:C語言技術網(www.freecplus.net) 日期:20190525
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct st_girl // 超女結構體
{
char name[50]; // 姓名
int age; // 年齡
};
int main(int argc,char *argv[])
{
int *pi=malloc(sizeof(int)); // 分配int類型大小的內存
long *pl=malloc(sizeof(long)); // 分配long類型大小的內存
double *pd=malloc(sizeof(double)); // 分配double類型大小的內存
char *pc=malloc(101); // 分配101字節的內存,可存放100個字符的字符串
struct st_girl *pst=malloc(sizeof(struct st_girl)); // 分配struct st_girl結構體大小的內存
// 以下代碼是像普通指針和變量一樣使用動態分配的內存
*pi=10; printf("*pi=%d\n",*pi);
*pl=20; printf("*pl=%d\n",*pl);
*pd=10.5; printf("*pd=%.1f\n",*pd);
strcpy(pc,"西施"); printf("*pc=%s\n",pc);
strcpy(pst->name,"楊玉環"); pst->age=21;
printf("name=%s,age=%d\n",pst->name,pst->age);
// 釋放動態分配的內存
free(pi); free(pl); free(pd); free(pc); free(pst);
}
運行效果
二、內存被耗盡
使用動態分配內存技術的時候,分配出來的內存必須及時釋放,否則會引起系統內存耗盡,這話說起來簡單,好像很容易做到,但是在實際開發中,程序員往往是漏洞百出。
內存問題是C程序員的主要問題之一,是初學者的惡夢。
三、野指針
野指針就是無效的指針,與空指針不同,野指針無法通過簡單地判斷是否爲 NULL避免,而只能通過養成良好的編程習慣來盡力減少。
1、指針變量未初始化
指針變量剛被創建時不一定會自動初始化成爲空指針(與編譯器有關),它的缺省值是可能隨機的,它會隨便亂指。所以,指針變量在創建的同時應當被初始化,要麼將指針的值設置爲0,要麼讓它指向合法的內存。
int *pi=0;
或
int i;
int *pi=&i;
2、指針釋放後之後未置空
指針在free時會把指針所指的內存給釋放掉,但指針不一定會賦值0(也與編譯器有關),如果對釋放後的指針進行操作,相當於非法操作內存。釋放內存後應立即將指針置爲0。
free(pi);
pi=0;
四、應用經驗
1、數組申明的改進
在C語言的早期標準中,定義數組必須用常量指明大小,不能用變量。
char str[101]; // 可以這樣
int len=101;
char str[len]; // 不可以這樣
程序在運行的時候,如果要定義一個字符串存放100個字符,那怎麼辦,只能通過動態分配內存技術。
char *str=malloc(101);
現在,定義數組可以用變量指明大小,就不必爲數組動態分配內存了。
還有,C++的string是一個變長的字符串,非常好用,程序員根本不必關心內存的問題。
2、鏈表
鏈表是C語言的一個經典的數據結構,相當於一個動態的結構體數組,非常巧妙,功能強大,但操作也麻煩,在這裏我就不介紹了。
在C++中,容器全完代替了鏈表的功能,極其好用,程序員也不必關心內存的問題。
3、我的建議
在中國,沒有純C程序員,如果他不會C++,不是他對C有多麼執着,可能是不會C++。
至少十年了,我不再使用動態內存分配技術,也想不到有什麼場景非得用動態內存分配技術。
哦,嵌入式開發可能是個例外,可能還有其它只能用C不能用C++的場景。
動態內存分配並不是什麼高大上的技術,我是一個實用的程序員,絕不給自己挖坑,這與水平高低無關。
五、課後作業
編寫示例程序,把本章節介紹的知識點全部演示一遍,用程序演示可以加深您的理解和映象。
六、版權聲明
C語言技術網原創文章,轉載請說明文章的來源、作者和原文的鏈接。
來源:C語言技術網(www.freecplus.net)
作者:碼農有道
如果文章有錯別字,或者內容有錯誤,或其他的建議和意見,請您留言指正,非常感謝!!!