王希琴
(包頭財經(jīng)學校,內(nèi)蒙古 包頭 014030)
C語言中變量的解析
王希琴
(包頭財經(jīng)學校,內(nèi)蒙古 包頭 014030)
通過對C語言中四種變量的不同方面的介紹,可以讓我們更精確地掌握它并根據(jù)實際情況選擇相應的變量來應用開發(fā)出高質(zhì)量的軟件.
作用域;存儲類型;全局變量;局部變量;靜態(tài)變量;寄存器變量
一直以來,對于初學者而言,函數(shù)就是一個比較難以掌握的問題,尤其是函數(shù)中的變量更是讓初學者理不出一個明確的思路,因而不能清晰的去掌握,所以也不敢去輕易地應用,浪費了c中精華、寶貴的資源.下面做一個簡單的總結(jié)和概括,希望能給初學者一點點的幫助.c的變量的應用分為以下幾個部分:
C程序的標識符作用域有三種:局部、全局、文件.標識符的作用域決定了程序中的哪些語句可以使用它,換句話說,就是標識符在程序其他部分的可見性.通常,標識符的作用域都是通過它在程序中的位置隱式說明的.
1.1 局部作用域.變量的局部作用域,他們都是聲明在函數(shù)或語句塊的內(nèi)部,無法被其他函數(shù)或語句塊的代碼所訪問.函數(shù)的形式參數(shù)的作用域也是局部的,它們的作用范圍僅限于函數(shù)內(nèi)部所用的語句塊.
上面例子里的兩個num變量都是局部變量,只在本身函數(shù)里可見.在兩個函數(shù)出現(xiàn)同名的變量不會互相干擾.所以上面的兩個輸出,在主函數(shù)里是5,在add()函數(shù)里輸出是6.
1.2 全局作用域.對于具有全局作用域的變量,我們可以在程序的任何位置訪問它們.當一個變量是在所有函數(shù)的外部聲明,也就是在程序的開頭聲明,那么這個變量就是全局變量.
上面的main()和add()里面,并沒有聲明num,在最后輸出的時候卻要求輸出num,這是由于在程序的開始聲明了num是全局變量,在所有函數(shù)里都可以使用這個變量.這時候一個函數(shù)里改變了變量的值,其他函數(shù)里的值也會出現(xiàn)影響.上面的例子輸出都是6,因為在add()函數(shù)里改變了num的值,由于num是全局變量,就好象它們兩個函數(shù)共用一個變量,所以在main()函數(shù)里的num也隨之改變了.
1.3 文件作用域.文件作用域在較大程序中很有作用.文件作用域是指外部標識符僅在聲明它的同一個轉(zhuǎn)換單元內(nèi)的函數(shù)中可見.所謂轉(zhuǎn)換單元是指定義這些變量和函數(shù)的源代碼文件.static存儲類型修飾符指定了變量具有文件作用域.
上面的程序中變量num和函數(shù)add()在聲明中采用了static存儲類型修飾符,這使得它們具有文件作用域.
前面我們說了,聲明變量時用如下形式:
它們都沒有存儲類型修飾符,我們在聲明時也可以通過存儲類型修飾符來告訴編譯器將要處理什么類型的變量.存儲類型有以下四種:自動(auto)、靜態(tài)(static)、外部(extern)、寄存器(regiser).
2.1 自動存儲類型.自動存儲類型修飾符指定了一個局部變量為自動的,這意味著,每次執(zhí)行到定義該變量的語句塊時,都將會為該變量在內(nèi)存中產(chǎn)生一個新的拷貝,并對其進行初始化.實際上,如果不特別指明,局部變量的存儲類型就默認為自動的.
在這個例子中,不論變量num的聲明是否包含關(guān)鍵字auto,代碼的執(zhí)行效果都是一樣的.函數(shù)的形式參數(shù)存儲類型默認也是自動的.
2.2 靜態(tài)存儲變量.前面已經(jīng)使用了static關(guān)鍵字,但是對于局部變量,靜態(tài)存儲類型的意義是不一樣的,這時,它是和自動存儲類型相對而言的.靜態(tài)局部變量的作用域仍然僅局限于聲明它的語句塊中,但是在語句塊執(zhí)行期間,變量將始終保持它的值.而且,初始化值只在語句塊第一次執(zhí)行時起作用.在隨后的運行過程中,變量將保持語句塊上一次執(zhí)行時的值.看下面兩個對應的程序:
上面兩個源文件,只有函add()里的變量聲明有所不同,一個是自動存儲類型,一個是靜態(tài)存儲類型.對于1.C文件,輸出結(jié)果為51 51 51;這很好理解,每次初始值都是50,然后加1上來.對于2.C文件,輸出結(jié)果為51 52 53;這是由于變量是靜態(tài)的,只在第一次初始化了50,以后都是使用上次的結(jié)果值.當?shù)谝淮握{(diào)用add()時,初始化為50,然后加1,輸出為51;當?shù)诙握{(diào)用時,就不初始化了,這時num的值為上次的51,然后加1,輸出52;當?shù)谌握{(diào)用時,num為52,加1就是53了.經(jīng)過比較就會發(fā)現(xiàn)它們的不同之處了.靜態(tài)變量在遞歸函數(shù)中經(jīng)常使用到.
2.3 外部存儲類型.外部存儲類型聲明了程序?qū)⒁玫降摹⒌形炊x的外部變量.通常,外部存儲類型都是用于聲明在另一個轉(zhuǎn)換單元中定義的變量.下面舉一個例子,這個例子包括兩個文件.
這兩個程序是分別編譯的,然后連接成一個執(zhí)行文件.把上面兩個文件都編譯好后,再制作一個.prj文件,里面的內(nèi)容是:第一行為1.c;第二行為2.c
可在編輯狀態(tài)下寫成,存盤,取名為1.prj.然后選擇project選項,選擇projectname,填入1.prj文件名,按F9后,即可生成1.exe文件.main()函數(shù)中變量num是在另一個文件中定義的.因此,當編譯器編譯1.c時,無法確定該變量的地址.這時,外部存儲類型聲明告訴編譯器,把所有對num的引用當作暫且無法確定的引用,等到所有編譯好的目標代碼連接成一個可執(zhí)行程序模塊時,再來處理對變量num的引用.
外部變量的聲明既可以在引用它的函數(shù)的內(nèi)部,也可以在外部.如果變量聲明在函數(shù)外部,那么同一轉(zhuǎn)換單元內(nèi)的所有函數(shù)都可以使用這個外部變量.反之,如果在函數(shù)內(nèi)部,那么只有這一個函數(shù)可以使用該變量.
前面說了文件作用域的問題,如果在聲明全局變量時,加上static修飾符,那么該變量只在當前文件內(nèi)可見,而extern又可以引用其它文件里的變量.所以在一個大型程序中,每個程序員只是完成其中的一小塊,為了讓自己的變量不讓其他程序員使用,保持一定的獨立性,經(jīng)常在全局變量前加static.
2.4 寄存器存儲類型.被聲明為寄存器存儲類型的變量,除了程序無法得到其地址外,其余都和自動變量一樣.
使用寄存器存儲類型的目的是讓程序員指定某個局部變量存放在計算機的某個硬件寄存器里而不是內(nèi)存中,以提高程序的運行速度.不過,這只是反映了程序員的主觀意愿,編譯器可以忽略寄存器存儲類型修飾符.寄存器變量的地址是無法取得的,因為絕大多數(shù)計算機的硬件寄存器都不占用內(nèi)存地址.而且,即使編譯器忽略寄存器類型修飾符把變量放在可設(shè)定地址的內(nèi)存中,我們也無法取地址的限制仍然存在.
要想有效的利用寄存器存儲類型,必須象匯編語言程序員那樣了解處理器的內(nèi)部構(gòu)造,知道可用于存放變量的寄存器的數(shù)量和種類,以及他們是如何工作的.但是,不同計算機在這些細節(jié)上未必是一樣的,因此對于一個可移植的程序來說,寄存器存儲類型的作用不大.特別是現(xiàn)在很多編譯器都能提供很好的優(yōu)化效果,遠比程序員來選擇有效的多.不過,寄存器存儲類型還是可以為優(yōu)化器提供重要的參考.
最后,還是總結(jié)一下定義為不同類型的變量的相同和不同之處,以便于更好地運用.
TP312
A
1673-260X(2010)02-0045-02
?