程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 全局變量與部分變量在內存中的差別具體解析

全局變量與部分變量在內存中的差別具體解析

編輯:關於C++

全局變量與部分變量在內存中的差別具體解析。本站提示廣大學習愛好者:(全局變量與部分變量在內存中的差別具體解析)文章只能為提供參考,不一定能成為您想要的結果。以下是全局變量與部分變量在內存中的差別具體解析正文


1、准備常識—法式的內存分派

一個由c/C++編譯的法式占用的內存分為以下幾個部門

1、棧區(stack)— 由編譯器主動分派釋放,寄存函數的參數值,部分變量的值等。其操作方法相似於數據構造中的棧。

2、堆區(heap) — 普通由法式員分派釋放, 若法式員不釋放,法式停止時能夠由OS收受接管 。留意它與數據構造中的堆是兩回事,分派方法卻是相似於鏈表。

3、全局區(靜態區)(static)—,全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域(.data),未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域(.bss)。 - 法式停止後由體系釋放。

4、文字常量區 —常量字符串就是放在這裡的(.rodata)。 法式停止後由體系釋放。

5、法式代碼區—寄存函數體的二進制代碼(.text)。

2、例子法式
這是一個先輩寫的,異常具體

//main.cpp
int a = 0;          // 全局初始化區
char *p1;           // 全局未初始化區
main()
{
  int b;            // 棧區
  char s[] = "abc"; // 棧區
  char *p2;         // 棧區
  char *p3 = "123456";     // "123456/0" 在常量區,p3在棧區
  static int c =0;         // 全局(靜態)初始化區

  p1 = (char *)malloc(10);
  p2 = (char *)malloc(20); // 分派得來的10和20字節的區域就在堆區

  strcpy(p1, "123456");    // "123456/0" 放在常量區,編譯器能夠會將它
                              // 與p3所指向的"123456"優化成一個處所。
}

static全局變量與通俗的全局變量有甚麼差別?static部分變量和通俗部分變量有甚麼差別?static函數與通俗函數有甚麼差別?

答:
1) 全局變量(內部變量)的解釋之前再冠以static 就組成了靜態的全局變量。全局變量自己就是靜態存儲方法, 靜態全局變量固然也是靜態存儲方法。 這二者在存儲方法上並沒有分歧。這二者的差別在於非靜態全局變量的感化域是全部源法式, 當一個源法式由多個源文件構成時,非靜態的全局變量在各個源文件中都是有用的。 而靜態全局變量則限制了其感化域, 即只在界說該變量的源文件內有用, 在統一源法式的其它源文件中不克不及應用它。因為靜態全局變量的感化域局限於一個源文件內,只能為該源文件內的函數公用,是以可以免在其它源文件中惹起毛病。

2) 從以上剖析可以看出, 把部分變量轉變為靜態變量後是轉變了它的存儲方法即轉變了它的生計期。把全局變量轉變為靜態變量後是轉變了它的感化域,限制了它的應用規模。                  

3) static函數與通俗函數感化域分歧,僅在本文件。只在以後源文件中應用的函數應當解釋為外部函數(static),外部函數應當在以後源文件中解釋和界說。關於可在以後源文件之外應用的函數,應當在一個頭文件中解釋,要應用這些函數的源文件要包括這個頭文件   

綜上所述:

static全局變量與通俗的全局變量有甚麼差別:

static全局變量只初使化一次,避免在其他文件單位中被援用;   

static部分變量和通俗部分變量有甚麼差別:

static部分變量只被初始化一次,下一次根據上一次成果值;   

static函數與通俗函數有甚麼差別:

static函數在內存中只要一份,通俗函數在每一個被挪用中保持一份拷貝

 ==============================================================
一個C說話變量分派的現實例子:
 
我們來看看在可履行文件中,變量們會被分派在哪些區裡.這裡以可履行文件為例子,可履行文件有固定的內存加載地址,符號(函數/變量的名字)未來在內存裡的地址銜接器是可以提早肯定的。

源法式編譯銜接的成果是構成1堆匯編指令代碼,年夜致分為.text .data .bss等幾個節區(section)。關於.exe文件和.so文件,全局和靜態變量都放在.data 或.bss段(gas把源文件從頭至尾掃描1遍,才曉得一個變量的全體情形:能否界說;類型;能否初始化。然後把初始化的變量在.data段裡分派地位和 空間,把沒初始化的變量在.bss段裡分派地位和空間,沒界說的變量分派在.undef段)。匯編指令代碼裡全局變量表示為一個內存地址(全局變量在目的 文件裡是一個偏移值,加載進內存裡是一個內存地址)。暫時變量在匯編代碼裡釀成ebp/esp+n,表示為一個客棧地址,化為法式注釋(.text)的一 部門。有些變量的終究內存地址在加載進內存之前還不克不及肯定,須要加載進內存才可以盤算出來.

全局變量 感化域是逾越多個源法式的。是以全局變量不克不及重名。靜態變量感化域是位於單個源法式內。多個源法式可以有同名的全局靜態變量。本例中,為了辨別多個同名的靜態變量,gcc 用 c444和c444.0 來加以差別。

[test@redhat]// more aaa.c
# include <stdio.h>
int a111 = 0;              // 全局變量 已初始化
char *p111 = "654321";     // 全局指針變量 曾經初始化
static int c444 = 9;       // 靜態全局變量 曾經初始化
static int c555;           // 靜態全局變量 未初始化
main()
{
    int b222;              // 部分變量
    char s333[] = "abc";   // 部分變量
    char *p222;            // 部分變量
    char *p333 = "123456";    // 部分變量
    static int c444 =0;       // 已初始化靜態部分變量,與後面靜態全局變量重名
    p111 = (char *)malloc(10);
    p222 = (char *)malloc(20);
    strcpy(p111, "123456");
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved