C語言之動態分配內存


1. malloc()函數和free()函數

首先,我們應該知道。所有的程序都必須留出足夠的內存空間來存儲所使用的數據,所以我們常常會預先給程序開辟好內存空間,然后進行操作,但事實上另一種選擇,能夠讓內存分配自己主動進行下去。

對於傳統數組,會遇到這種問題:

int arr[5] ;

對這個數組我們在定義的時候必須給提前開辟好空間。而且在程序運行的過程中,這個開辟的內存空間是一直存在的。除非等到這個函數運行完成,才會將空間釋放。

另一個問題就是這個數組在程序中無法被改動。


這些問題給我們造成了一些使用上的不方便,所以,C中提供了malloc()函數。
關於malloc()函數。這個函數它接受一個參數:就是所需的內存的字節數。然后malloc()找到可用內存中那一個大小適合的塊。在這個過程中,malloc()能夠來返回那塊內存第一個字節的地址。所以。也就意味了我們能夠使用指針來操作。malloc()能夠用來返回數組指針、結構指針等等。所以我們須要把返回值的類型指派為適當的類型。當malloc()找不到所需的空間時。它將返回空指針。


例:

double *p;
p=(double*)malloc(30*sizeof(double));

在這個程序中,首先開辟了30個double類型的空間,然后把p指向這個空間的位置。在這里的指針是指向第一個double值。

並非我們所有開辟的30個double的空間。

這就和數組一樣,指向數組的指針式指向數組首元素的地址,並非整個數組的元素。所以,在這里我們的操作也和數組是一樣的,
p[0]就是第一個元素。p[2]就是第二個元素。
至此。我們就能夠掌握到一種聲明動態數組的方法。

int arr[n];
p=(int *)malloc(n*sizeof(int));
//我們在這里使用的時候要元素個數乘類型字節長度。這樣就達到了動態開辟內存空間。

當我們使用malloc()開辟完內存空間以后,我們所要考慮的就是釋放內存空間,在這里,C給我們提供了free()函數。

free()的參數就是malloc()函數所返回的地址,釋放先前malloc()函數所開辟的空間。
例:
對於上面我們所開辟的空間進行釋放,那么我們就能夠這樣

free(p);

程序還調用了exit()函數,這個函數是在內存分配失敗時結束程序。
程序樣例:


#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>//malloc()函數被包括在malloc.h里面
#include<stdlib.h>
int main(void)
{
    char*a = NULL;//聲明一個指向a的char*類型的指針
    a = (char*)malloc(100 * sizeof(char));//使用malloc分配內存的首地址。然后賦值給a
    if (!a)//假設malloc失敗。能夠得到一些log
    {
        perror("malloc");
        return-1;
    }
    sprintf(a, "%s", "HelloWorld\n");//"HelloWorld\n"寫入a指向的地址
    printf("%s\n", a);//輸出用戶輸入的數據
    free(a);//釋放掉使用的內存地址
    system("pause");
    return 0;//例2有無內存泄露?
}

這個程序主要用來檢測malloc返回值條件有誤。
在這里我們須要注意,在C中,類型指派(char *)是可選的,可是在C++中這個是必須有的,所以使用類型指派將使把C程序移植到C++更easy。

使用動態數組,主要是為了獲得程序的靈活性。我們嗯能夠須要多少個元素就讓數組開辟多少個。。

不須要浪費空間

2.free()的重要性

在我們使用malloc()函數的時候。分配的內存是會添加的,當我們使用free()函數時,能夠釋放內存。
比如:
...

int main()
{
    double glad[2000];
    int i;
    ...
    for(i=0;i<1000;i++)
        gobble(glad,2000);
    ...
}
void gobble(double arr[],int n)
{
    double *temp=(double *)malloc(n*sizeof(double));
    ...
}

在這個程序其中我們使用了malloc()函數,可是我們沒有使用free()函數,在這個程序中,我們首先進入gobble()函數,穿件了指針temp,而且使用了malloc()函數。可是除了gobble()函數之后,指針作為一個變量消失了,可是所開辟的內存是依舊存在的,我們依舊開辟了16000個字節的內存。

可是我們卻無法去訪問這些內存。由於他們的地址不見了。由於沒有調用free()函數,這段內存也不能再此使用了。
這樣依次循環。總共運行for循環1000次。終於導致了程序總共16000000個字節的內存無法使用,這樣。內存肯定已經溢出了。

這樣就會出現我們所說的程序泄漏問題,而free()函數,正好攻克了這種的問題。

3.calloc()函數和realloc()函數

接下來。我們在認識兩個關於內存分配的函數。calloc()函數和realloc()函數。
calloc()函數與malloc()函數有同樣之處。也有類似之處。
例:

short *p;
newmem=(short *)calloc(1000sizeof(short)); 

通過這個樣例,我們能夠知道calloc()函數有兩個參數。而且這兩個函數都是size_t類型(unsigned int類型)的數。

第一個參數在這里所說的是所須要開辟的內存單元數量。第二個參數是每一個單元的字節的大小。

void *calloc(size_t ,size_t);

calloc()函數另一個特性。它將塊中的所有位都置為0。這也是calloc()函數和malloc()函數的差別,calloc()函數和malloc()函數的另外一個差別是他們請求內存數量的方式不一樣。當然。free()函數也能夠來釋放calloc()函數分配的內存。

realloc()函數用來改動一個原先已經分配的內存的大小。使用這個函數,你能夠讓一塊內存增大還是縮小。當擴大時。這塊內存原先的內容會依舊保留,新添加的加入到原先的后面。縮小時,該內存的尾部部分內存去掉,剩余保留。

注意:對於realloc()函數。假設原先的內存無法改動。這時候realloc()函數再會分配一塊內存。而且把原先那塊內存的內容拷貝到上面去。

所以。使用了realloc函數以后,你這時候在使用的就該是realloc函數返回的新指針了。當realloc函數的第一個參數是NULL時,這時候我們能夠把它當作是malloc()函數。

寫博客已經半個月了,感覺問題還是非常多。希望大家多多指點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM