1. 程式人生 > 實用技巧 >何時使用或何時不使用malloc函式?學資料結構有感

何時使用或何時不使用malloc函式?學資料結構有感

在學資料結構時,我們往往不太清楚在定義一個結構體指標時要不要使用malloc函式。
例如以下的程式碼:

LINKLIST  *init linklist()
{
    LINKLIST *H=NULL;
    LINKLIST *S;
    int x;
    printf("請輸入連結串列元素 或以-1結束輸入")
    while(x!=-1)
    {
      s=(LINKLIST*)malloc(sizeof(LINKLIST));
      s->data=x;
      s->next=H;
      H=s;
      scanf(%d,&x);
    }
retrun H;
}

在定義結構體指標變數S時需要用到malloc函式
而定義結構體指標變數H時則沒有用到malloc函式
S和H的區別所在是:H沒有指向有效地記憶體地址,而S指向了有效地記憶體地址,因為S指向了有效地記憶體地址所以可以往S指向的記憶體地址裡面寫值:S->data=x;而在後來H指向的地址就是每一個新的S指向的地址:H=S;


再舉個例子

LINKLIST *S;
S->data=x;

以上這兩句程式碼是不行的,因為S沒有指向確切的地址,所以不能通過S來向它要指向的地址賦值;
但是

LINKLIST *S;
LINKLIST P;
S=&P;
S->data=x;

是可以的,因為S指向P的地址,S->data=x;等同於p.data=x;
而malloc的作用就類似以上程式碼的作用;但是不用再定義一個結構變數P,再讓結構體指標變數S指向它的地址&P,而是使用malloc函式讓結構體指標變數S指向一個確切的記憶體地址

LINKLIST *s;
s=(LINKLIST*)malloc(sizeof(LINKLIST));
s->data=x;

為什麼要?何時要?

  malloc()是動態記憶體分配函式,用來向系統請求分配記憶體空間。當無法知道記憶體具體的位置時,想要繫結真正的記憶體空間,就要用到malloc()函式。因為malloc只管分配記憶體空間,並不能對分配的空間進行初始化,所以申請到的記憶體中的值是隨機的,經常會使用memset()進行置0操作後再使用。  

  與其配套的是free()當申請到的空間不再使用時,要用free()函式將記憶體空間釋放掉,這樣可以提高資源利用率,最重要的是----就是因為它可以申請記憶體空間,然後根據需要進行釋放,才被稱為“動態記憶體分配”! 

  

  比如在資料結構中定義圖的鄰接表儲存時

//將鄰接矩陣MG轉換為鄰接表AG
void MatToList(MGraph MG,ALGraph *&AG)
{
    int n=MG.vexnum;//n存放圖節點個數,方便書寫
    ArcNode *p;
    AG=(ALGraph *)malloc(sizeof(ALGraph));//【手動申請空間並初始化鄰接表,必須進行malloc,否則程式不能執行!】
    for(int i=0;i<n;i++)
        AG->adjlist[i].firstarc=NULL; //習慣性,malloc完就初始化 如memset

    for(int i=0;i<n;i++)
        for(int j=n-1;j>=0;j--)//注意遍歷順序,【這會影響後面連結串列新增節點使用頭插法還是尾插法!】
            if(MG.edges[i][j]!=0&&MG.edges[i][j]!=INF)
            {
                p=(ArcNode *)malloc(sizeof(ArcNode));
                p->adjvex=j;//弧頭指向的節點
                p->weight=MG.edges[i][j];//弧的權
                p->nextarc=AG->adjlist[i].firstarc;//頭插法新增節點,因為前面是節點數值大的往前遍歷的,因此順序正好是0-1-3!
                AG->adjlist[i].firstarc=p;
            }
    AG->n=n;
    AG->e=MG.arcnum;
}

malloc 和free的形象解釋:

  malloc()函式實質體現在,它有一個可以將可用記憶體塊連線成一個長長的列表的連結串列,這個連結串列就是所謂的空閒連結串列。呼叫malloc()函式時,它沿著連線表尋找一個大到可以滿足使用者請求要求的連續的記憶體塊,然後將記憶體塊一分為二,一塊的大小與使用者請求的記憶體大小相等,另一塊就是剩下的記憶體塊。接下來,它將使用者申請的那塊傳遞給使用者,將另一塊返回到連線表上(如果另一塊有的話)。 

  呼叫free()函式的時候,它將使用者想要釋放的記憶體塊連結到空閒鏈上。我們可以想到,最後的空閒鏈連結的記憶體空間一小塊一塊的塊,如果這是使用者申請分配一個較大的記憶體空間,那麼空閒鏈上可能沒有符合使用者要求的記憶體塊了,這個時候,malloc()函式請求延時,並開始在空閒鏈上翻箱倒櫃的檢查各記憶體塊,對他們進行整理,將相鄰的小記憶體塊合併成較大的記憶體塊。如果無法獲得符合用於要求的記憶體空間,那麼malloc()函式就會返回NULL,因此,呼叫malloc()函式的時候,一定要判斷它的返回值是否為NULL。

參考

https://blog.csdn.net/wstz_5461/article/details/74356690?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control