C 堆變量,棧變量,指針參數,非指針參數 剖析

1.基本概念

  • 堆(Heap)
    程序能夠動態申請的存儲空間,經過malloc系列函數分配,全局可訪問。數據結構

  • 棧(Stack)
    這裏說的棧不是數據結構中LIFO的棧,而是進程虛擬地址空間的棧;程序在進行函數調用時動態伸縮的存儲空間,侷限於函數內能夠訪問。函數

-堆變量(Heapvariables)
數據存儲在堆的變量,全局可訪問。spa

  • 棧變量(Stackvariables)
    函數中聲明的局部變量,只能在函數內部訪問,不然訪問行爲的結果是未定義的。指針

  • 指針參數(Pointerparameters)
    參數類型爲指針的參數。code

  • 非指針參數(Non-pointerparameters)
    參數類型不是指針的參數。進程

2.進程的虛擬地址空間

進程虛擬地址空間

3.相關問題剖析

3.1 如何正確的分配內存

demo代碼

void * fun_m1()
{
    char buf[100];
    return (void *)buf;
}

void * fun_m2(size_t size)
{
    return malloc(size);
}

void fun_m3(size_t size, void * p)
{
    p = malloc(size);
}

void fun_m4(size_t size, void ** p)
{
    *p = malloc(size);
}

剖析

  • fun_m1是錯誤的,由於它返回的棧變量的地址,若是對它指向的地址進行讀寫,程序行爲的結果是未定義的,程序極可能崩潰,由於此時棧變量的空間已經被回收(棧頂指針改變了)。內存

  • fun_m2是正確的,由於它返回的是malloc申請的堆空間的地址。rem

  • fun_m3和fum_m4很具備迷惑性,要分區fun_m3和fun_m4的區別,咱們這裏須要澄清一個概念:任何的參數傳遞本質上都是值拷貝,任何參數都是棧變量。it

  • 在咱們以往觀念中參數傳遞就是兩種:值傳遞,指針傳遞,而經過指針能夠改變指針指向的變量。io

  • 爲何說參數傳遞都是值拷貝呢,這是由於無論參數是否爲指針,傳遞的都是一份值的拷貝,只不過當你的參數類型爲指針時,你傳遞的是指針變量的值,而經過*操做符做用在指針變量上,你又恰好能夠影響到指針變量關聯的其餘變量的值。

  • 經過上面的剖析咱們能夠知道fun_m3是錯誤的,由於沒有*操做符做用在p上,單純對p賦值操做只會影響到局部的棧變量p的值,而不會對函數fun_m3外的變量有任何影響。fun_m4是正確的,由於有*操做符做用在p上,經過對*p賦值來修改傳遞給p的參數,使它指向申請的堆空間。

3.2 如何判斷堆和棧的「增加」方向(從低到高,仍是從高到低)

判斷棧的「增加」方向

#include <stdio.h>
#include <malloc.h>

void fun1(int * pb)
{
    int a;
    printf("stack alloc direction[%s]\n", &a > pb ? "Up" : "Down");
}

void fun2()
{
    int b;
    fun1(&b);
}

int main()
{
    fun2();
    return 0;
}

編譯運行

[root@iZ940zytujjZ test]# gcc -o test10 test10.c
[root@iZ940zytujjZ test]# ./test10
stack alloc direction[Down]
[root@iZ940zytujjZ test]#

從運行結果看,棧的增加方向是「從高到低」(Down)。

判斷堆的「增加」方向

#include <stdio.h>
#include <unistd.h>
#include <malloc.h>

int main()
{
    void * a = sbrk(10);    //調整堆頂指針brk
    void * b = sbrk(20);
    printf("heap alloc direction[%s]\n", b > a ? "Up" : "Down");
    return 0;
}

編譯運行

[root@iZ940zytujjZ test]# gcc -o test11 test11.c
[root@iZ940zytujjZ test]# ./test11
heap alloc direction[Up]
[root@iZ940zytujjZ test]#

從運行結果看,堆的增加方向是「從低到高」(Up)。

相關文章
相關標籤/搜索