一、預備知識―程序的內存分配
一個由c/C++編譯的程序占用的內存分為以下幾個部分
1、棧區(stack)― 由編譯器自動分配釋放,存放函數的參數值,局部變量的值等。其操作方式類似于數據結構中的棧。
2、堆區(heap) ― 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似于鏈表。
3、全局區(靜態區)(static)―,全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域(.data),未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域(.bss)。 - 程序結束后由系統釋放。
4、文字常量區 ―常量字符串就是放在這里的(.rodata)。 程序結束后由系統釋放。
5、程序代碼區―存放函數體的二進制代碼(.text)。
二、例子程序
這是一個前輩寫的,非常詳細
答:
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 來加以區別。
|
新聞熱點
疑難解答
圖片精選