C語言記憶體分布

來源:互聯網
上載者:User

標籤:class   初始化   org   init   一個   變數   函數   不能   結果   

C語言記憶體分布

典型的C語言程式記憶體表示分區共有5個部分:

  1. 本文段 Text segment
  2. 已初始化資料區段(資料區段)Initialized data segment
  3. 未初始化資料區段(bss)Uninitialized data segment
  4. 堆 Stack
  5. 棧 Heap
具體分布圖

各個分區的作用
  • 本文段
    • CPU執行的機器指令部分
    • 通常可共用
    • 常常是唯讀
  • 已初始化資料區段(資料區段)
    • 包含程式中需明確賦初始值的變數
    • 儲存已經初始化的全域變數
  • 未初始化資料區段(BSS)
    • 在程式開始執行之前,核心將此段中的資料初始化為0或null 指標
    • 儲存未初始化的全域變數(注意:即使是賦值為0也是未初始化!
    • 儲存自動變數及每次函數調用所需儲存的資訊
    • 每次函數調用時,存放其返回地址及調用者的環境資訊(如某些機器寄存器的值)
    • 為最近被調用的函數分配自動變數和臨時變數的儲存空間
    • 動態儲存裝置分配
初始化?

上面提到,對全域變數來說,如果是賦值為0仍是未初始化。下面給出實際實驗結果:

範例程式碼1
#include <stdio.h>int a;int main(int argc, char const *argv[]){    printf("hello\n");    return 0;}

編譯後查看記憶體分布:

範例程式碼2
#include <stdio.h>int a = 0;int main(int argc, char const *argv[]){    printf("hello\n");    return 0;}

編譯後查看記憶體分布:

可以看到,各個儲存地區數值沒有變化。

範例程式碼3
#include <stdio.h>int a = 1;int main(int argc, char const *argv[]){    printf("hello\n");    return 0;}

編譯後查看記憶體分布:

可以看到,對全域變數進行真正的初始化之後,bss少了4個位元組,data段多出了4個位元組。

關於static的問題範例程式碼4

先看看相對上一例子,多了一個局部變數之後的記憶體分布。

#include <stdio.h>int a = 1;int main(int argc, char const *argv[]){    int b;    printf("hello\n");    return 0;}

編譯後查看記憶體分布:

可以看到,記憶體分布是沒有變化的,局部變數b會在棧上分配到記憶體。

範例程式碼5

如果把b定義成static呢?

#include <stdio.h>int a = 1;int main(int argc, char const *argv[]){    static int b;    printf("hello\n");    return 0;}

編譯後查看記憶體分布:

可以看到,此時bss上多出了8個位元組。

範例程式碼6

如果給b賦初始值0呢?

#include <stdio.h>int a = 1;int main(int argc, char const *argv[]){    static int b = 0;    printf("hello\n");    return 0;}

編譯後查看記憶體分布:

可以看到,跟上一個例子相比沒有變化,說明跟全域變數一樣,static變數賦值為0仍是未初始化。

範例程式碼7

如果給b賦初始值1呢?

#include <stdio.h>int a = 1;int main(int argc, char const *argv[]){    static int b = 1;    printf("hello\n");    return 0;}

編譯後查看記憶體分布:

可以看到,bss少了4個位元組,而data多了4個位元組,說明靜態變數和全域變數同理,初始化之後是存在data段中的。

關於static的用處範例程式碼8
#include <stdio.h>int x = 4;void incre() {    static int x = 1;    x *= x + 1;    printf("%d\n", x);}int main(int argc, char const *argv[]){    int i;    for (i = 1; i < x; i++) {        incre();    }    return 0;}

運行結果為:

可以看到,函數increx的範圍存在於其局部,但是卻在每次調用函數的時候沿用之前的值!這是因為static定義的變數是靜態變數,有著靜態儲存位置(變數儲存位置固定不動,若在代碼中已經初始化則存在於data段,否則存在於bss段),而不是存在於棧上,因此每次調用函數讀取到的變數的值都是靜態儲存區的值。

static的意義:
  1. 全域靜態變數
    • 不會被其它檔案所訪問和修改
    • 其它檔案中可以使用相同名字的變數,不會發生衝突
  2. 局部靜態變數
    • 可以用作計數器,每次函數調用的時候可以進行計數
  3. 靜態函數
    • 其它檔案中可以定義相同名字的函數,不會發生衝突
    • 靜態函數不能被其它檔案所用
    • 靜態函數會被分配在一個一直使用的儲存空間,直到程式退出,避免了調用函數時進棧出棧,提升運行速度
參考書目
  1. Unix環境進階編程(中文第三版)
  2. C primer plus(中文第五版)
參考部落格

C語言儲存空間布局以及static詳解——奔人之旅

C語言記憶體分布

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.