天天看點

全局變量和局部變量在記憶體裡的差別

一、預備知識—程式的記憶體配置設定 一個由c/C++編譯的程式占用的記憶體分為以下幾個部分 1、棧區(stack)— 由編譯器自動配置設定釋放,存放函數的參數值,局部變量的值等。其操作方式類似于資料結構中的棧。 2、堆區(heap) — 一般由程式員配置設定釋放, 若程式員不釋放,程式結束時可能由OS回收 。注意它與資料結構中的堆是兩回事,配置設定方式倒是類似于連結清單。 3、全局區(靜态區)(static)—,全局變量和靜态變量的存儲是放在一塊的,初始化的全局變量和靜态變量在一塊區域(.data),未初始化的全局變量和未初始化的靜态變量在相鄰的另一塊區域(.bss)。 - 程式結束後由系統釋放。 4、文字常量區 —常量字元串就是放在這裡的(.rodata)。 程式結束後由系統釋放。 5、程式代碼區—存放函數體的二進制代碼(.text)。 二、例子程式 這是一個前輩寫的,非常詳細 //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函數與普通函數有什麼差別? 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 來加以差別。

[[email protected]]# more aaa.c

# include # char s333[] = “abc”;

0x0804839c # char *p333 = “123456”;

0x080483a4 # p111 = (char *)malloc(10);

0x080483ab # p222 = (char *)malloc(20);

0x080483bd # strcpy(p111, “123456”);

0x080483cd