C語言學習筆記(13)

來源:互聯網
上載者:User

1. 動態記憶體分配

先來介紹三個動態記憶體分配的函數:malloc,calloc和realloc。說來慚愧,以前只知道malloc。現在來看下他們的區別:

malloc:最常用的分配記憶體塊,但是不對記憶體進行初始化。

calloc:分配記憶體塊,但是對記憶體塊進行清零操作,這就造成此函數的效率要比malloc要低。

realloc:調整(增加或者減少)之前分配記憶體塊的大小。

由於上面的函數只是開闢了一段記憶體,因此無法知道你要利用這段記憶體來儲存什麼類型的資料,因此只是返回一個void *類型的值,當然,void *可以和任何指標類型互相轉換。

當分配記憶體失敗時(可能是記憶體不足或者其他原因),以上的函數都會返回一個null 指標,那麼我們安全期間,在我們使用這塊分配的記憶體前,都應該進行一次null 指標的驗證。

int main (void){    int *p;    p=(int *)malloc(sizeof(*p)*1000);    if(p==NULL)    {        exit(EXIT_FAILURE);    }    printf("success");    return 0;}

注意上面的兩點,一個是null 指標的驗證,另外一個是分配記憶體的大小,這裡我們常常是用類型的大小乘以儲存成員的數量來計算分配。如果是字串,我們就不要忘記了加1,來儲存\0。

#include <stdio.h>#include <stdlib.h>int main (void){    char *p;    p=(char *)malloc(sizeof(*p)*1000+1);    if(p==NULL)    {        exit(EXIT_FAILURE);    }    printf("success");    return 0;}

 

接下來我們看一下calloc元素的原型:

void * __cdecl calloc(_In_ size_t _Count, _In_ size_t _Size);

從上面我們可以看到calloc函數有兩個參數,分配是,數量和大小。由此可以說明,calloc是C語言用來分配數組空間最好的選擇。那麼我們就把第一段代碼改一下:

int main (void){    int *p;    p=(int *)calloc(1000,sizeof(int));    if(p==NULL)    {        exit(EXIT_FAILURE);    }    printf("success");    return 0;}

這樣就更合適了。

最後是realloc,我們也來看一下realloc元素的原型:

void * __cdecl realloc(_Post_ptr_invalid_ void * _Memory, _In_ size_t _NewSize);

 

當我們之前分配了一個數組的大小,但是後來我們卻發現這個大小不夠用了,或者是太大了,那麼我們就可以利用realloc來調整我們的佔用記憶體大小:

int main (void){    int *p;    p=(int *)calloc(1000,sizeof(int));    if(p==NULL)    {        exit(EXIT_FAILURE);    }    realloc(p,sizeof(int)*100);    if(p==NULL)    {        exit(EXIT_FAILURE);    }    printf("success");    return 0;}

也別忘了檢驗p是否為空白指標的情況。

在C標準中,並沒有對realloc的實現做以規定,但是對於大部分編譯器來說,如果是把原地址空間縮小,他會盡量地不去移動原來的資料。如果是把空間增大,那麼他會盡量首先在原地址的末尾去分配記憶體,如果不足以分配,那麼編譯器才會去尋找新的地址塊,並且把原地址空間內的資料轉移到新的地址上。

2. 釋放空間

習慣了Java/C#的我們,似乎已經忘記了要回收垃圾的習慣,在C/C++中,是沒有GC的,因此我們要記得,當我們在堆上分配了一塊記憶體,並且不在使用時,我們要使用free函數來釋放掉空間。看下free的原型:

void   __cdecl free(_Post_ptr_invalid_ void * _Memory);

很簡單,不再贅述。

3. 指向指標的指標

在讀大學時,我一直對這個概念不是很理解,現在我更願意這樣去理解指標。

當我們聲明了int *p=malloc(1000)的時候,我們可以這樣來理解:

其實我更願意把p就理解成一個地址的值,p=0x1111(0x1111是分配的1000位元組記憶體的首地址)。那麼什麼是指向指標的指標呢?

這裡的q就是指向指標的指標,q的值就是0x0004,也就是p所在的地址。

以此類推,我們還可以知道指向指標的指標的指標。

4. 函數指標

我們來看C語言裡提供了qsort函數:

_CRTIMP void __cdecl qsort(_Inout_bytecap_x_(_NumOfElements * _SizeOfElements) void * _Base,     _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements,         _In_ int (__cdecl * _PtFuncCompare)(const void *, const void *));

 

最後一個參數就是一個函數指標,其實不用這麼麻煩,我們來看個簡單的函數指標的原型:

double (*function)(int);

這個就是最簡單的函數指標的原型,與返回指標類型的函數相比,他們相差的只是*和函數名之間要用括弧括起來。

當傳進來一個函數指標時,我們便可以在函數中適用這個傳進來的參數(函數指標)了。例如在qsort裡,我們便可以自己制定比較規則,不再多說。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.