全局變量與局部變量在內(nèi)存中的區(qū)別詳細(xì)解析
一、預(yù)備知識—程序的內(nèi)存分配
一個(gè)由c/C++編譯的程序占用的內(nèi)存分為以下幾個(gè)部分
1、棧區(qū)(stack)— 由編譯器自動分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
2、堆區(qū)(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由OS回收 。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式倒是類似于鏈表。
3、全局區(qū)(靜態(tài)區(qū))(static)—,全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域(.data),未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域(.bss)。 - 程序結(jié)束后由系統(tǒng)釋放。
4、文字常量區(qū) —常量字符串就是放在這里的(.rodata)。 程序結(jié)束后由系統(tǒng)釋放。
5、程序代碼區(qū)—存放函數(shù)體的二進(jìn)制代碼(.text)。
二、例子程序
這是一個(gè)前輩寫的,非常詳細(xì)
//main.cpp
int a = 0; // 全局初始化區(qū)
char *p1; // 全局未初始化區(qū)
main()
{
int b; // 棧區(qū)
char s[] = "abc"; // 棧區(qū)
char *p2; // 棧區(qū)
char *p3 = "123456"; // "123456/0" 在常量區(qū),p3在棧區(qū)
static int c =0; // 全局(靜態(tài))初始化區(qū)
p1 = (char *)malloc(10);
p2 = (char *)malloc(20); // 分配得來的10和20字節(jié)的區(qū)域就在堆區(qū)
strcpy(p1, "123456"); // "123456/0" 放在常量區(qū),編譯器可能會將它
// 與p3所指向的"123456"優(yōu)化成一個(gè)地方。
}
static全局變量與普通的全局變量有什么區(qū)別?static局部變量和普通局部變量有什么區(qū)別?static函數(shù)與普通函數(shù)有什么區(qū)別?
答:
1) 全局變量(外部變量)的說明之前再冠以static 就構(gòu)成了靜態(tài)的全局變量。全局變量本身就是靜態(tài)存儲方式, 靜態(tài)全局變量當(dāng)然也是靜態(tài)存儲方式。 這兩者在存儲方式上并無不同。這兩者的區(qū)別在于非靜態(tài)全局變量的作用域是整個(gè)源程序, 當(dāng)一個(gè)源程序由多個(gè)源文件組成時(shí),非靜態(tài)的全局變量在各個(gè)源文件中都是有效的。 而靜態(tài)全局變量則限制了其作用域, 即只在定義該變量的源文件內(nèi)有效, 在同一源程序的其它源文件中不能使用它。由于靜態(tài)全局變量的作用域局限于一個(gè)源文件內(nèi),只能為該源文件內(nèi)的函數(shù)公用,因此可以避免在其它源文件中引起錯(cuò)誤。
2) 從以上分析可以看出, 把局部變量改變?yōu)殪o態(tài)變量后是改變了它的存儲方式即改變了它的生存期。把全局變量改變?yōu)殪o態(tài)變量后是改變了它的作用域,限制了它的使用范圍?! ?nbsp;
3) static函數(shù)與普通函數(shù)作用域不同,僅在本文件。只在當(dāng)前源文件中使用的函數(shù)應(yīng)該說明為內(nèi)部函數(shù)(static),內(nèi)部函數(shù)應(yīng)該在當(dāng)前源文件中說明和定義。對于可在當(dāng)前源文件以外使用的函數(shù),應(yīng)該在一個(gè)頭文件中說明,要使用這些函數(shù)的源文件要包含這個(gè)頭文件
綜上所述:
static全局變量與普通的全局變量有什么區(qū)別:
static全局變量只初使化一次,防止在其他文件單元中被引用;
static局部變量和普通局部變量有什么區(qū)別:
static局部變量只被初始化一次,下一次依據(jù)上一次結(jié)果值;
static函數(shù)與普通函數(shù)有什么區(qū)別:
static函數(shù)在內(nèi)存中只有一份,普通函數(shù)在每個(gè)被調(diào)用中維持一份拷貝
==============================================================
一個(gè)C語言變量分配的實(shí)際例子:
我們來看看在可執(zhí)行文件中,變量們會被分配在哪些區(qū)里.這里以可執(zhí)行文件為例子,可執(zhí)行文件有固定的內(nèi)存加載地址,符號(函數(shù)/變量的名字)將來在內(nèi)存里的地址連接器是可以提前確定的。
源程序編譯連接的結(jié)果是形成1堆匯編指令代碼,大致分為.text .data .bss等幾個(gè)節(jié)區(qū)(section)。對于.exe文件和.so文件,全局和靜態(tài)變量都放在.data 或.bss段(gas把源文件從頭到尾掃描1遍,才知道一個(gè)變量的全部情況:是否定義;類型;是否初始化。然后把初始化的變量在.data段里分配位置和 空間,把沒初始化的變量在.bss段里分配位置和空間,沒定義的變量分配在.undef段)。匯編指令代碼里全局變量表現(xiàn)為一個(gè)內(nèi)存地址(全局變量在目標(biāo) 文件里是一個(gè)偏移值,加載進(jìn)內(nèi)存里是一個(gè)內(nèi)存地址)。臨時(shí)變量在匯編代碼里變成ebp/esp+n,表現(xiàn)為一個(gè)堆棧地址,化為程序正文(.text)的一 部分。有些變量的最終內(nèi)存地址在加載進(jìn)內(nèi)存之前還不能確定,需要加載進(jìn)內(nèi)存才可以計(jì)算出來.
全局變量 作用域是跨越多個(gè)源程序的。因此全局變量不能重名。靜態(tài)變量作用域是位于單個(gè)源程序內(nèi)。多個(gè)源程序可以有同名的全局靜態(tài)變量。本例中,為了區(qū)分多個(gè)同名的靜態(tài)變量,gcc 用 c444和c444.0 來加以區(qū)別。
[test@redhat]// more aaa.c
# include <stdio.h>
int a111 = 0; // 全局變量 已初始化
char *p111 = "654321"; // 全局指針變量 已經(jīng)初始化
static int c444 = 9; // 靜態(tài)全局變量 已經(jīng)初始化
static int c555; // 靜態(tài)全局變量 未初始化
main()
{
int b222; // 局部變量
char s333[] = "abc"; // 局部變量
char *p222; // 局部變量
char *p333 = "123456"; // 局部變量
static int c444 =0; // 已初始化靜態(tài)局部變量,與前面靜態(tài)全局變量重名
p111 = (char *)malloc(10);
p222 = (char *)malloc(20);
strcpy(p111, "123456");
}
上一篇:C/C++語言中結(jié)構(gòu)體的內(nèi)存分配小例子
欄 目:C語言
本文標(biāo)題:全局變量與局部變量在內(nèi)存中的區(qū)別詳細(xì)解析
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3981.html
您可能感興趣的文章
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10深入理解atoi()與itoa()函數(shù)的用法
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10基于atoi()與itoa()函數(shù)的內(nèi)部實(shí)現(xiàn)方法詳解
- 01-10Linux線程管理必備:解析互斥量與條件變量的詳解
- 01-10深入理解大數(shù)與高精度數(shù)的處理問題
- 01-10深入理解數(shù)組指針與指針數(shù)組的區(qū)別
- 01-10C語言游戲必備:光標(biāo)定位與顏色設(shè)置的實(shí)現(xiàn)方法
- 01-10深入探討C語言中局部變量與全局變量在內(nèi)存中的存放位置
- 01-10linux c 查找使用庫的cflags與libs的方法詳解


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10C#中split用法實(shí)例總結(jié)
- 04-02jquery與jsp,用jquery
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改