指針作為形參和返回值的區別


關於指作為針形參與返回值的常見問題

1、返回棧中局部變量的地址

#include <stdio.h>

int *fun(){
    int a = 10; // a為當前方法棧中的局部變量,結束即釋放
    return &a;  // 所以傳遞出去的會是一個無效(非法)地址
}

int main(int argc, char const *argv[])
{
    int *a = NULL;
    a = fun();
    *a = 100;   // error,操作非法內存
    printf("a = %d\n", *a);
    return 0;
}

2、返回data區的地址

代碼同上,不同之處在於a加個static,變為靜態局部變量,等同於全局變量

#include <stdio.h>

int *fun(){
    static int a = 10; // 靜態局部變量,不會隨着方法棧自動釋放
    return &a; // 返回的是有效地址
}

int main(int argc, char const *argv[])
{
    int *a = NULL;
    a = fun();
    *a = 100;   // ok
    printf("a = %d\n", *a);
    return 0;
}

3、指針作為形參傳遞(一)

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

void fun(int *tmp){
    tmp = (int *)malloc(sizeof(int));   // 形參局部指針變量只在當前方法棧中有效
    *tmp = 100;  // 當前棧中tmp動態分配的內存未釋放,造成內存泄漏
}

int main(int argc, char const *argv[])
{
    int *p = NULL;
    fun(p); // p是空指針,沒有指向,把p的值傳給tmp
    printf("*p = %d\n", *p);    // error 操作空指針所指向的內存
    return 0;
}    

此時fun()函數和main()函數同級,tmp作為fun中的形參局部變量,對其操作不會影響main中的實參p;

並且給tmp在堆中動態分配內存,但是tmp隨着fun方法棧的釋放而消失,堆中的內存沒有釋放,造成內存泄漏。

4、指針作為形參傳遞(二)

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

void fun(int *tmp){
    *tmp = 100;
}

int main(int argc, char const *argv[])
{
    int *p = NULL;
    p = (int *)malloc(sizeof(int));
    fun(p); // 值傳遞
    printf("*p = %d\n", *p);    // 100
    return 0;
}

此時在fun()函數中操作的不是指針變量tmp,而是tmp所指向的堆內存(沒有改形參本身),也就是fun()方法棧中和main()方法棧中的兩個變量tmp和p指向了同一塊堆內存,fun()方法棧的釋放並不會影響操作結果

5、指針作為返回值

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

int * fun(){
    int *tmp = NULL;
    tmp = (int *)malloc(sizeof(int));   // 在堆中分配內存
    *tmp = 100;                         // 堆內存賦值
    return tmp;                         // 返回堆區地址,函數調用完畢不釋放
}

int main(int argc, char const *argv[])
{
    int *p = NULL;
    p = fun(p);
    printf("*p = %d\n", *p);    // 100

    // free :堆區空間需要手動釋放
    if (p != NULL) {
        free(p);
        p = NULL;
    }
    
    return 0;
}

和第3的區別在於不是通過形參給變量賦值,而是直接返回了指針變量,注意:這里返回的不是棧區的局部變量地址(第1),而是堆區的地址,堆區變量是不會自動釋放的,所以返回是合法的。

指針指向同圖4


免責聲明!

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



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