C語言中pi=&j和*pi=j的區別

xumenger發表於2019-05-12

C語言中的指標是一個難點,主要是感覺很繞,其實C/C++中的指標和Delphi的指標的原理都是一樣的,所以這裡講的一個C/C++的例子也適用於Delphi

原始碼如下

int i, j;
int *pi, *pj;

i=10;
j=9;
pi=&i;    //相當於將指標 pi 指向 i 的地址

//比較下面兩個語句
pi=&j;    //這時候是將指標 pi 指向 j 的地址,並不會對i有什麼影響
*pi = j;    //在這是將 j 的值賦值給 pi 所指向的那個變數,所以就相當於 i = j;

所以這兩個語句並不是等價的,要先去理解指標的指向和實際的記憶體的關係,再結合語言的上下文就可以理解這些語句的實際意義,並不要沒有根據的瞎猜

理解這兩者的區別是很有用的,因為程式設計時候可能有這樣的情況,需要一個函式在內部完成功能的時候,要自己去分配記憶體,而且需要在呼叫的時候傳遞進來指標來儲存這個分配的記憶體的地址,以便能在這個函式執行結束之後,能夠不丟失去這個分配的記憶體的指標,能在外面進行釋放,不至於造成記憶體洩露。

比如有兩個函式:DoSomeThing()和FreeTheMem(),前者是做某些事,並且自己分配需要的記憶體,後者是釋放掉DoSomeThing()分配的記憶體,比如呼叫關係是這樣的

char *pchar;    //這個指標的目的是為了傳進DoSomeThing,記錄DoSomeThing分配的記憶體的地址

DoSomeThing(&pchar);

FreeTheMem(pchar);

所以對應的DoSomeThing和FreeTheMem的實現是這樣的

void DoSomeThing(char **ppchar)
{
    char *pc;
    //為pc分配記憶體,比如 pc = (char*)malloc(sizeof(char));
    //利用分配的記憶體來做一些事....
  
    *ppchar = pc;
    //這裡的傳入的引數 char** ppchar是用於做輸出引數的,而不是作為輸入引數
    //因為在主函式中呼叫的形式是DoSomeThing(&pchar),
    //所以就相當於pchar=pc; 這就是想要的效果,
    //就是用主函式中pchar儲存被呼叫的DoSomeThing裡面的記憶體的地址

    //如果要是使用ppchar=&pc;,
    //但是因為在主函式中呼叫的形式是DoSomeThing(&pchar),
    //所以在這裡就相當於&pchar = &pc,所以顯然不是想要的效果

}

void FreeTheMem(char *pchar)
{
    ...釋放pchar所指向的記憶體...
}

另外一個需要講解的知識點,為什麼要在DoSomeThing裡面分配的記憶體,因為可能需要將在DoSomeThing裡面處理的一些結果儲存到這個記憶體中,供呼叫它的函式再使用,然後使用完這個記憶體中儲存的資訊之後,再去釋放記憶體

所以這裡就需要動態分配記憶體,因為如果你在DoSomeThing裡面用一個陣列來儲存這些資訊,但是當DoSomeThing結束之後,這個陣列的生命週期也就結束了,所以這時候的陣列就被釋放了(這種情況下的陣列的記憶體是在棧上分配的),想要儲存的資訊也就丟失了,所以一定要是動態分配的記憶體(動態分配的記憶體是在堆上的)。

其實C++的兩種宣告物件的方法也和這個類似。

相關文章