C語言編程之動態(tài)內存與柔性數組的了解
創(chuàng)建變量
1,局部變量–棧區(qū)
2,全局變量–靜態(tài)區(qū)
創(chuàng)建數組
1,局部數組–棧區(qū)
2,全局數組–靜態(tài)區(qū)
介紹動態(tài)內存分配函數
malloc
free
calloc
realloc
所有的動態(tài)內存分配,都是在堆中進行分配
分別介紹動態(tài)內存函數
malloc
void* malloc(size_t size)
向內存堆中申請size個字節(jié),并返回該空間的首地址。同時定義一個指針來接受函數返回的地址。
如:
int* p=(int*)malloc(10*sizeof(int));
開辟了40個字節(jié)的動態(tài)空間,進行了類型轉換,就像開辟了10個int類型的空間。
如果開辟失敗,就會返回一個空指針NULL。
所以,使用指針時要檢查。否則會因空指針造成非法訪問。
當動態(tài)空間不再使用時,就要將空間返回給內存,防止堆滿了。
free
釋放空間
void free(void* memblock(要釋放的空間的首地址))
free只是釋放掉堆中的空間,但定義的指針是在棧中,并不會被銷毀,也就是說,指針儲存的地址依然存在,所定義的指針仍然可以指向那個空間,但空間已經被銷毀,不具備訪問權限,會造成非法訪問。
free(p); p=NULL;
不僅釋放空間,還要,將指針置為空指針,就無法訪問了。
每次動態(tài)分配內存都要判斷是否成功。
calloc
開辟一個數組空間,并將每個元素都置為0
void* calloc(size_t num,size_t size)
num代表是元素個數,size代表每個元素的字節(jié)數。calloc將在堆中開辟一個數組,并將每個元素都置為0.返回開辟空間的首地址。同時要考慮用一個對應指針來接受。
realloc
調整動態(tài)開辟空間的大小
void* realloc(void* memblock,size_t size);
舉個例子
int* p=(int*)malloc(5*sizeof(int)) int* pp=(int*)realloc(p,10*sizeof(int)) if(p!=NULL&&pp!=NULL) { p=pp; }
這樣使用后就會將p指向的空間調整為10個int空間的動態(tài)空間。
realloc使用細節(jié)
1,在堆區(qū)中,malloc開辟了一塊空間,再使用realloc增加空間,諾可以滿足直接在原空間直接增加空間,就會直接追加,并返回原來地址。
2,諾無法滿足條件,后面無法追加足夠的空間,就會在堆區(qū)重新創(chuàng)建一個滿足追加后的大小的空間,并將原空間的字節(jié)一一復制到這個新空間,并自動free掉原空間,返回新建空間的首地址,如果realloc失敗,就會返回NULL
就是說,如果realloc要的空間較大,可能會開辟一個新的空間,改變返回的地址,所以要定義新的指針來接受realloc的返回地址。
常見的動態(tài)內存開辟的錯誤
1,malloc開辟失敗未判斷
if(p==NULL) { printf("%S",strerror(error)); } else { 開辟成功 }
2,對動態(tài)開辟空間的越界訪問
3,對非動態(tài)開辟空間的釋放
int num[10];在棧區(qū)開辟的不能free free(num); num=NULL;
4,對同一塊動態(tài)內存進行多次釋放,所以要p=NULL,這樣再次釋放就沒意義。
5,對動態(tài)空間未釋放,會導致堆中滿了,造成內存泄漏。
6,free了一部分動態(tài)空間,因為p的指向位置發(fā)生了改變,p不能改變。
舉個例子
#include <stdio.h> void num(char* p) { p = (int*)malloc(100); } void test(void) { char* str = NULL; num(str); strcpy(str, "abcdef"); printf(str); } int main(void) { test(); return 0; }
有形式參數,存放在棧區(qū)。
一旦函數結束,就會被銷毀,無法使用。
p只是str的形參,利用p開辟空間,但不會影響str。所以str還是NULL,strcpy會造成非法訪問。
但這叫,傳值操作。可以通過傳址操作,可以改變實參??梢允褂?/p>
1,二級指針,傳址調用,地址是不會銷毀
2,使用return,在銷毀之前,就返回了動態(tài)空間的地址。
free只會銷毀堆中的空間,但地址都還在棧中,不會受影響。
柔性數組
可以人為設置數組大小的數組。
要在結構體中設置。
struct s { int n; int arr[0]; }; sizeof(struct s)
當計算大小時,是不會計算柔性數組的大小。
除非,后面,使用malloc。
struct s* p = malloc(sizeof(struct s) + 4 * sizeof(int));
可以這樣動態(tài)開辟一個空間。同時為數組開辟一個空間。
可以p->arr[i]訪問到數組。
柔性數組的特點
1,結構體中柔性數組成員前至少有一個其他類型的成員。
2,sizeof返回結構體大小不包括柔性數組的內存大小
還有指針類型的
struct s { int n; int* arr; }; int main(void) { struct s* p = (struct s*)malloc(sizeof(struct s)); p->arr =(int*) malloc(10 * sizeof(int)); }
arr得到這個開辟的空間的首地址,同時還強轉成了int*指針,這種也創(chuàng)建了一個數組。
同時還可以多次修改這個數組的大小。
每次釋放內存時先
free(p->arr),要先找到這個數組空間,
再free(P)。
注意,當內存是連續(xù)的,可以提高訪問效率,也有利于減少內存碎片,提高訪問速度。
同時,多次malloc會增加內存碎片,降低空間使用效率。
以上就是C語言編程之動態(tài)內存與柔性數組的了解的詳細內容,更多關于C語言的資料請關注腳本之家其它相關文章!
感謝閱讀~
相關文章
C++利用 _findfirst與_findnext查找文件的方法
這篇文章主要給大家介紹了關于C++利用 _findfirst與_findnext查找文件的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-06-06