C語言 動態記憶體開闢

2021-08-25 05:52:26 字數 3945 閱讀 2484

我們已經掌握的記憶體開闢方式有:

int val = 20;//在棧空間上開闢四個位元組

char arr[10] = ;//在棧空間上開闢10個位元組的連續空間

但是上述開闢空間的方式有兩個特點:

1.空間開闢的大小是固定的。

2.陣列在宣告的時候,必須指定陣列的長度,它所需要的內存在編譯時分配。

但是對於空間的要求,不僅僅是上述的情況。有時候我們需要的空間大小在程式執行的時候才能知道,那陣列的編譯時開闢空間的方式就不能滿足了,這時候就引入了動態記憶體開闢:

動態記憶體開闢的函式:

void* malloc(size_t size);
這個函式向記憶體申請一塊連續可用的空間,並返回指向這塊空間的指標。

-如果開闢成功,則返回乙個指向開闢好空間的指標。

-如果開闢失敗,則返回乙個null指標,因此malloc的返回值一定要做檢查。

- 返回值的型別是void*,所以malloc函式並不知道開闢空間的型別,具體在使用的時候使用者自己來決定。

- 如果引數size為0,malloc的行為是標準未定義的,取決於編譯器。

同時c語言還提供了另外乙個函式free,專門用來做動態記憶體釋放和**的,函式原型如下:

void free(void* ptr);
free 函式用來釋放動態開闢的記憶體。

-如果引數ptr指向的空間不是動態記憶體開闢的,那free函式的行為是未定義的。

-如果引數ptr是null指標,則函式什麼都不做。

舉個例子:

#include int main()

;    //**2

int* ptr = null;

ptr = (int*)malloc(num*sizeof(int));

if (null != ptr)

}free(ptr);//釋放ptr所指向的動態記憶體

ptr = null;//置空

return 0;

}

c語言還提供了乙個函式叫calloc,calloc函式也用來動態記憶體分配。原型如下:

void* calloc(size_t num, size_t size);
-此函式的功能為num個大小為size的元素開闢一塊空間,並且把空間的每個位元組初始化為0.

-與函式malloc的區別在於calloc會在返回位址之前把申請的空間的每個位元組初始化為全0.舉個例子:

#include #include int main()

free(p);

p = null;

return 0;

}

所以如何對我們申請的記憶體空間要求初始化,那麼可以很方便的使用calloc函式來完成任務。

-realloc函式的出現讓動態記憶體管理更加靈活。

-有時我們發現過去申請的空間太小了,有時候我們又會覺得申請的空間過大了,那為了合理使用記憶體,我們一定會對記憶體的大小做靈活的調整。那realloc函式就可以做到對動態開闢記憶體大小的調整。函式原型如下:

void* realloc (void* ptr,size_t 

-ptr是要調整的記憶體位址

-size是調整之後新大小

-返回值為調整之後的記憶體起始位置。

-這個函式調整原記憶體空間大小的基礎上,還會將原來記憶體中的資料移動到新的空間。

-realloc在調整記憶體空間的時候存在兩種情況:

情況1:原有空間之後有足夠大的空間

當是情況1的時候,要擴充套件記憶體就直接在原有記憶體之後直接追加空間,原來空間的資料不發生變化。

情況2:原有空間之後沒有足夠大的空間

當是情況2的時候,原有空間之後沒有足夠多的空間時,擴充套件的方法是:在棧空間上另找乙個合適大小的連續空間來使用。這樣函式返回的是乙個新的記憶體位址。

由於有兩種情況,所以使用realloc函式時得注意一些。

舉個例子:

#include int main()

else

//擴充套件容量

//**1

int* p = null;

p = realloc(ptr, 1000);

if (p != null)

//業務處理

free(ptr);

return 0;

}

>對null指標的解引用操作

void test()

解決辦法:在解引用之前先判斷p是否為null

>對動態開闢空間的越界訪問

void test()

for (i = 0; i <= 10; i++)

free(p);

}

>對動態開闢記憶體使用free釋放

void test()

>使用free釋放一塊動態開闢記憶體的一部分

void test()

解決辦法:對於動態開闢的空間不要使用p++或++p

>對同一塊動態記憶體多次釋放

void test()

解決辦法:釋放完一次後,直接把p賦值給null指標

>動態記憶體忘記釋放(記憶體洩露)

void test()

}int main()

忘記釋放不再使用的動態開闢的空間會造成記憶體洩漏。

切記:動態記憶體開闢的空間一定要釋放,並且正確釋放。

題目1:

void getmemory(char *p)

void test(void)

請問執行test函式會有什麼樣的結果 ?

問題:程式崩潰,記憶體洩露

原因:getmemory函式中的形參p出函式時會銷毀,沒有把malloc開闢的空間帶回去,會出現記憶體洩露;

形參p出函式時銷毀,沒人知道它指向的那塊空間在哪,所以str仍舊為null,程式會奔潰。

題目2:

void getmemory(void)

void test(void)

請問執行test函式會有什麼樣的結果?

問題:輸出的str是隨機值

原因:返回時,因為p是形參,一出getmemory函式,p裡面的東西被銷毀,返回的位址裡面就是隨機值,所以str輸出的就是隨機值。

題目3:

void getmemory2(char **p,int num)

void test(void)

問題:記憶體洩露,需要free

題目4:

void test(void)

}

問題:程式是錯誤的,釋放完後,沒有把str賦值為null

修改:釋放完後,把str賦值為null,去判斷,才有意義。

題目5:

int *fl(void)

int *f2(void)

問題:指標沒有被初始化,位址裡面放的是隨機值,並不是乙個有效的位址,10不允許放進去,放進去,位址無效,也列印不出來

分析:p裡面存的是隨機的位址,解引用後,通過隨機值找了一塊空間,10不允許被放進去。(ptr裡面存的是無效的指標,也稱ptr為野指標)

(C語言)動態記憶體開闢

資料的元素儲存於記憶體中連續的位置上,當乙個陣列被宣告時,他所需要的內存在編譯時就被分配。當然,我們也可以使用動態記憶體分配在執行時為他分配記憶體。在動態記憶體分配中我們需要經常用到malloc,free,calloc,realloc這四個函式。malloc和free分別用於執行動態記憶體分配和釋放...

C語言 動態記憶體開闢

動態記憶體開闢是根據使用者的需要來開闢開間,是在堆上開闢空間的。用於開闢一塊連續的記憶體空間。函式原型 void malloc size t size malloc函式的返回值是乙個void型別的指標,引數為無符號型別資料即申請分配的記憶體大小,單位是位元組。記憶體開闢成功,返回這塊空間的首位址,失...

C動態記憶體開闢

動態記憶體開闢 malloc calloc realloc 都是在堆上申請空間 一 malloc和free void malloc size t size 動態開闢記憶體 include include include int main int ptr int malloc 10 sizeof in...