C語言編程之動態(tài)內(nèi)存與柔性數(shù)組的了解
創(chuàng)建變量
1,局部變量–棧區(qū)
2,全局變量–靜態(tài)區(qū)
創(chuàng)建數(shù)組
1,局部數(shù)組–棧區(qū)
2,全局數(shù)組–靜態(tài)區(qū)
介紹動態(tài)內(nèi)存分配函數(shù)
malloc
free
calloc
realloc
所有的動態(tài)內(nèi)存分配,都是在堆中進行分配
分別介紹動態(tài)內(nèi)存函數(shù)
malloc
void* malloc(size_t size)
向內(nèi)存堆中申請size個字節(jié),并返回該空間的首地址。同時定義一個指針來接受函數(shù)返回的地址。
如:
int* p=(int*)malloc(10*sizeof(int));
開辟了40個字節(jié)的動態(tài)空間,進行了類型轉(zhuǎn)換,就像開辟了10個int類型的空間。
如果開辟失敗,就會返回一個空指針NULL。
所以,使用指針時要檢查。否則會因空指針造成非法訪問。
當動態(tài)空間不再使用時,就要將空間返回給內(nèi)存,防止堆滿了。
free
釋放空間
void free(void* memblock(要釋放的空間的首地址))
free只是釋放掉堆中的空間,但定義的指針是在棧中,并不會被銷毀,也就是說,指針儲存的地址依然存在,所定義的指針仍然可以指向那個空間,但空間已經(jīng)被銷毀,不具備訪問權(quán)限,會造成非法訪問。
free(p); p=NULL;
不僅釋放空間,還要,將指針置為空指針,就無法訪問了。
每次動態(tài)分配內(nèi)存都要判斷是否成功。
calloc
開辟一個數(shù)組空間,并將每個元素都置為0
void* calloc(size_t num,size_t size)
num代表是元素個數(shù),size代表每個元素的字節(jié)數(shù)。calloc將在堆中開辟一個數(shù)組,并將每個元素都置為0.返回開辟空間的首地址。同時要考慮用一個對應(yīng)指針來接受。
realloc
調(diào)整動態(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指向的空間調(diào)整為10個int空間的動態(tài)空間。
realloc使用細節(jié)
1,在堆區(qū)中,malloc開辟了一塊空間,再使用realloc增加空間,諾可以滿足直接在原空間直接增加空間,就會直接追加,并返回原來地址。
2,諾無法滿足條件,后面無法追加足夠的空間,就會在堆區(qū)重新創(chuàng)建一個滿足追加后的大小的空間,并將原空間的字節(jié)一一復(fù)制到這個新空間,并自動free掉原空間,返回新建空間的首地址,如果realloc失敗,就會返回NULL
就是說,如果realloc要的空間較大,可能會開辟一個新的空間,改變返回的地址,所以要定義新的指針來接受realloc的返回地址。
常見的動態(tài)內(nè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)內(nèi)存進行多次釋放,所以要p=NULL,這樣再次釋放就沒意義。
5,對動態(tài)空間未釋放,會導(dǎo)致堆中滿了,造成內(nè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; }
有形式參數(shù),存放在棧區(qū)。
一旦函數(shù)結(jié)束,就會被銷毀,無法使用。
p只是str的形參,利用p開辟空間,但不會影響str。所以str還是NULL,strcpy會造成非法訪問。
但這叫,傳值操作??梢酝ㄟ^傳址操作,可以改變實參??梢允褂?/p>
1,二級指針,傳址調(diào)用,地址是不會銷毀
2,使用return,在銷毀之前,就返回了動態(tài)空間的地址。
free只會銷毀堆中的空間,但地址都還在棧中,不會受影響。
柔性數(shù)組
可以人為設(shè)置數(shù)組大小的數(shù)組。
要在結(jié)構(gòu)體中設(shè)置。
struct s { int n; int arr[0]; }; sizeof(struct s)
當計算大小時,是不會計算柔性數(shù)組的大小。
除非,后面,使用malloc。
struct s* p = malloc(sizeof(struct s) + 4 * sizeof(int));
可以這樣動態(tài)開辟一個空間。同時為數(shù)組開辟一個空間。
可以p->arr[i]訪問到數(shù)組。
柔性數(shù)組的特點
1,結(jié)構(gòu)體中柔性數(shù)組成員前至少有一個其他類型的成員。
2,sizeof返回結(jié)構(gòu)體大小不包括柔性數(shù)組的內(nèi)存大小
還有指針類型的
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得到這個開辟的空間的首地址,同時還強轉(zhuǎn)成了int*指針,這種也創(chuàng)建了一個數(shù)組。
同時還可以多次修改這個數(shù)組的大小。
每次釋放內(nèi)存時先
free(p->arr),要先找到這個數(shù)組空間,
再free(P)。
注意,當內(nèi)存是連續(xù)的,可以提高訪問效率,也有利于減少內(nèi)存碎片,提高訪問速度。
同時,多次malloc會增加內(nèi)存碎片,降低空間使用效率。
以上就是C語言編程之動態(tài)內(nèi)存與柔性數(shù)組的了解的詳細內(nèi)容,更多關(guān)于C語言的資料請關(guān)注腳本之家其它相關(guān)文章!
感謝閱讀~
相關(guān)文章
從匯編看c++中函數(shù)里面的static關(guān)鍵字的使用說明
c++中的static關(guān)鍵字使得函數(shù)里面的局部變量的存活期不在局限于函數(shù)里面,而是變?yōu)樵谡麄€程序生命期里面都有效2013-05-05C語言輪轉(zhuǎn)數(shù)組的三種實現(xiàn)
輪轉(zhuǎn)數(shù)組是一種將數(shù)組元素循環(huán)移動的處理方式,它通常用于解決一些需要對固定長度的數(shù)組進行循環(huán)滾動處理的問題,本文就介紹了C語言輪轉(zhuǎn)數(shù)組的三種實現(xiàn),感興趣的可以了解一下2023-08-08C++利用 _findfirst與_findnext查找文件的方法
這篇文章主要給大家介紹了關(guān)于C++利用 _findfirst與_findnext查找文件的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-06-06