1. 程式人生 > >【C語言】動態記憶體分配小結

【C語言】動態記憶體分配小結

為什麼存在動態記憶體分配?

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

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

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

1.空間開闢的大小是固定的 2.陣列在申明的時候,必須指定陣列的長度,它所需要的記憶體在編譯時分配

但是對於空間的需求,不僅僅是上面的情況,有時候我們需要的空間大小在程式執行的時候才能知道,那陣列的編譯時開闢空間的方式就不能滿足了

動態記憶體分配的介紹:

C語言提供了一個動態開闢的函式:

void malloc(size_t size);

這個函式向記憶體申請一塊連續可用的空間,並返回指向這塊空間的指標。

  • 如果開闢成功,則返回一個指向開闢好空間的指標。
  • 如果開闢失敗,則返回一個NULL指標,因此malloc的返回值一定要做檢查。
  • 返回值的型別是void*, 所以malloc函式並不知道開闢空間的型別,具體在使用的時候使用者自己來決定。
  • 如果引數size為0,malloc的行為是 標準是未定義的,取決於編譯器。
  • C語言提供了另外一個函式free, 專門是用來做動態記憶體的釋放和回收的

函式原型如下:

void free(void* ptr);

free函式用來釋放動態開闢的記憶體。

  • 如果引數ptr指向的空間不是動態幵闢的, 那free函式的行內是未定乂的。
  • 如果引數ptr是NULL指標, 則函式什麼事都不做。

malloc

malloc和free都宣告在stdlib.h標頭檔案中。

例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	int *p = (int*)malloc(10 * sizeof(int));
	int i = 0;
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 0;
	}
	//開闢成功
	for (i = 0; i < 10; i++)
	{
		*(p + i) = 10 - i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", *(p + i));
	}
	free(p);
	p = NULL;
	system("pause");
	return 0;
}

calloc

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

void* calloc(size_t num, size_t size);

函式的功能是為num個大小為size 的元素開闢一塊空間, 並且把空間的每個位元組初始化為0

與函式malloc的區別只在於calloc會在返回地址之前把申請的空間的每個位元組初始化為全0。

舉個例子 :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	int *p = (int*)calloc(10, sizeof(int));
	int i = 0;
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 0;
	}
	//開闢成功
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", *(p + i));
	}
	free(p);
	p = NULL;
	system("pause");
	return 0;
}

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

realloc

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

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

函式原型如下 :

void realloc(void* ptr, size_t size);

ptr是要調整的記憶體地址 size  調整之後新大小 返回值為調整之後的記憶體起始位置。 這個函式調整原記憶體空間大小的基礎上,還會將原來記憶體中的資料移動到新的空間。 realloc在調整記憶體空間的是存在兩種情況 : 情況1 : 原有空間之後有足夠大的空間 情況2 : 原有空間之後沒有足夠大的空間

情況1: 當是情況1的時候,要擴充套件記憶體就直接原有記憶體之後直接追加空間,原來空間的資料不發生變化。 情況2: 當是情況2的時候,原有空間之後沒有足夠多的空間時,擴充套件的方法是 : 在堆空間上另找一個合適大小的連續空間來使用。這樣函式返回的是一個新的記憶體地址。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	int *p = malloc(10 * sizeof(int));
	int i = 0;
	int *ptr = NULL;
	if (p == NULL)
	{
		return 0;
	}
	for (i = 0; i < 10; i++)
	{
		p[i] = i;
	}
	ptr = realloc(p, 20 * sizeof(int));
	if (ptr != NULL)
	{
		p = ptr;
	}
	for (i = 0; i < 20; i++)
	{
		printf("%d\n", p[i]);
	}
	free(p);
	p = NULL;
	system("pause");
	return 0;
}