- 零基礎學單片機C語言程序設計
- 趙建領 薛園園等編著
- 2756字
- 2018-12-31 21:41:35
3.6 變量作用域
變量作用域是程序中變量起作用的范圍。由于C51中可以包含多個函數和程序文件,因此使用變量時,除要首先定義該變量外,還要注意變量的有效作用范圍,即該變量的作用域。變量作用域即變量的作用范圍,可以是作用于一個函數或一個程序文件,甚至整個工程里的所有文件都可用。一般而言,按照變量的存儲類型,變量分為自動變量、全局變量、靜態變量和寄存器變量4種類型。下面將分別介紹其作用域范圍。
3.6.1 變量作用域的基本規則
在C51語言中,任何以花括號括起來的一段程序稱為一個塊結構,通常稱為復合語句。最典型的塊結構是函數或者for、if、do和while等語句。C51中規定,在塊結構中進行定義的變量,其有效使用范圍只在該塊結構內部,示例如下。
#include <stdio.h> //頭文件 void main() //主函數 { int i; //在main函數中定義整型變量 i=15; //變量賦值 { //塊結構 int t; //在塊結構中定義整型變量 t=2; //變量賦值 } printf("i=%d",i); //輸出變量i,正確 printf("t=%d",t); //輸出變量t,錯誤 }
其中,整型變量i定義在主函數的大括號內,其使用范圍為整個主函數。因此,后面的打印輸出i的語句是正確的。而整型變量t定義在塊結構內,因此其只在該塊結構中使用,出了該塊結構便無效了。因此,最后的打印輸出t的語句是錯誤的,在編譯程序時,系統將會提示該變量未聲明。
由于塊結構內部的變量只在其內部有效,因此,即使塊結構內定義的變量與塊結構外定義的變量具有相同的變量名,它們之間也不會發生沖突。程序示例如下。
#include <stdio.h> //頭文件 void main() //主函數 { int i; //定義整型變量 i=15; //變量賦值 { //塊結構 int i; //定義整型變量 i=2; //變量賦值 printf("in block i=%d\n",i); //輸出變量i } printf("out block i=%d\n",i); //輸出變量i }
這段程序可在Keil μ Vision3集成開發環境中運行,程序輸出結果如下。
in block i=2 out block i=15
該程序中,在主函數以及塊結構中均定義了整型變量i,但各有不同的作用域。在塊結構內部,其內部定義的變量i起作用,外部定義的變量被屏蔽,因此程序輸出i為2。在塊結構外部,是主函數定義變量的有效范圍,塊結構內部的變量將消失,因此程序輸出i為15。
3.6.2 自動變量
自動變量一般在是函數的內部或者程序塊中時使用,是以關鍵字auto標識的變量類型。其定義格式為“[auto]類型說明符變量標識符,變量標識符...”。自動型變量的作用域范圍是函數或者程序塊的內部。
在編譯C51程序時,自動型變量根據變量類型動態分配存儲空間。在程序執行到該函數時,根據變量類型為其自動分配存儲空間,當該函數執行完畢后,立即取消該變量的存儲空間,即該自動型變量失效。這樣在該函數內部定義的變量,就不能在該函數外引用。使用自動變量的程序示例如下。
#include <stdio.h> //頭文件 void main() //主函數 { int i=8; //定義整型變量 int t=6; //定義整型變量 { //程序塊1開始 int i=15; //定義整型變量 int t=25; //定義整型變量 { //程序塊2開始 int i=20; //定義整型變量 int t=30; //定義整型變量 printf("i=%d,t=%d\n",i,t); //輸出 } //程序塊2結束 printf("i=%d,t=%d\n",i,t); //輸出 } //程序塊1結束 printf("i=%d,t=%d",i,t); //輸出 }
這段程序可在Keil μ Vision3集成開發環境中運行,執行結果如下。
i=20,t=30 i=15,t=25 i=8,t=6
在該程序中,主函數聲明了整型變量i和t,然后分別嵌套兩個塊結構的復合語句,其中分別定義并初始化變量i和t。根據前面的介紹,這里定義的各個變量都默認為自動變量,雖然變量名相同,其作用域僅限于函數內部和塊結構內部,不會影響外部的變量。
說明
在C51中,函數或程序塊內部定義的變量,一般都默認為自動型變量。因此,在不聲明自動型變量時,關鍵字auto一般都可以省略。
3.6.3 全局變量
全局變量一般定義在所有函數的外部,即整個程序文件的最前面,也稱為外部變量。全局變量的作用域是整個程序文件,即全局變量可以被該程序文件中的任何函數使用。
在編譯C51程序時,全局變量根據變量類型被靜態地分配適當的存儲空間。在整個程序運行過程中,該變量一旦分配空間,便不會消失。這樣全局變量對整個程序文件都有效。
全局變量是永久性的,因此全局變量可以作為不同函數間的參數進行傳遞和共享。全局變量的程序示例如下。
#include <stdio.h> //頭文件 double PI=3.14159; //圓周率PI int r; //整型全局變量,表示半徑 double FunctionS() //計算面積函數 { double S; S=r*r*PI; //計算圓的面積 return S; //返回圓的面積 } void main() //主函數 { r=4; //半徑賦值 printf("If r=%d, S=%f\n",r, FunctionS()); //輸出圓的面積 }
這段程序可在Keil μ Vision3集成開發環境中運行,執行結果如下。
If r=4, S=50.265440
該程序在源文件的頭部定義了浮點型的全局變量PI表示圓周率、整型的全局變量r表示圓的半徑。整型變量r在主函數中初始化,然后在FunctionS()函數中調用,用來計算并返回圓的面積。
對于比較復雜的C51程序,其一般以工程項目的形式來組織多個程序文件。此時,全局變量允許在一個程序文件中定義,而同時可以在另一個程序文件中使用。為了方便使用,需要在文件的頭部用關鍵字“extern”來對全局變量進行引用聲明。這樣該C51項目在編譯的時候,可以自動在其他程序文件中尋找該全局變量,從而知道該全局變量的數據類型和值。
上面的程序可以采用這種方法來實現,將程序分兩個文件。FunctionS.c程序文件代碼如下。
#include <stdio.h> //頭文件 double PI=3.14159; int r; double FunctionS() //計算面積函數 { double S; S=r*r*PI; //計算圓的面積 return S; //返回圓的面積 }
主程序main.c文件代碼如下:
#include <stdio.h> //頭文件 extern PI; extern r; double FunctionS(); void main() //主函數 { r=4; //半徑賦值 printf("If r=%d, S=%f\n",r, FunctionS()); //輸出圓的面積 }
這段程序可在Keil μ Vision3集成開發環境中運行,執行結果如下。
If r=4, S=50.265440
該程序實現的功能和前面是一樣的,只不過分為兩個程序文件來實現。在FunctionS.c文件中定義了浮點型的全局變量PI表示圓周率、整型的全局變量r表示圓的半徑。在主程序文件main.c中使用這兩個變量前,首先用extern關鍵字加以聲明,這樣便可以使用FunctionS.c文件中定義的全局變量PI和r了。
3.6.4 靜態變量
靜態變量即在編譯C51程序時,根據數據類型靜態地分配合適的存儲空間,并在程序運行過程中始終占有該存儲空間的變量。以關鍵字static定義,其定義格式為“static<類型說明符> <變量標識符>,<變量標識符>...”,示例如下。
static int i; static char c;
在C51語言中,根據變量聲明位置的不同,靜態變量可以分為如下兩種。
?內部靜態變量,即在函數內部定義,其作用域只是定義該變量的函數內部,和自動變量類似。
?外部靜態變量,即在函數外部定義,其始終占有內存空間,和全局變量類似。
除了靜態變量外,C51語言還允許將自定義函數定義為靜態型,同樣用static關鍵字來定義。這樣,只有同一程序文件中的其他函數才能調用這個靜態型函數,而工程項目中的其他程序文件則不能調用訪問。使用靜態型函數既有利于程序的模塊化設計,又可以防止和其他文件中的函數發生重名的情況。
3.6.5 寄存器變量
寄存器變量被存儲在CPU的寄存器中。寄存器變量以關鍵字register聲明,聲明格式為“register類型說明符變量標識符,變量標識符...”,示例如下。
register char ch; register double db;
由于寄存器變量被存儲在CPU的寄存器中,因此其讀寫速度比較高。寄存器變量常用于某一變量名頻繁使用的情況,這樣做可以提高系統的運算速度。
在使用寄存器變量時需要注意如下幾點。
?由于單片機內部寄存器數量有限,不能定義多個寄存器變量。在實際程序設計中,應將最重要的變量設置為寄存器變量,以提高系統執行速度。
?在C51中,只允許同時定義兩個寄存器變量,如果多于兩個,程序在編譯時會自動地將兩個以外的寄存器變量作為非寄存器變量來處理。
- 簡單高效LATEX
- Vue.js快跑:構建觸手可及的高性能Web應用
- 編寫整潔的Python代碼(第2版)
- Instant Typeahead.js
- 嚴密系統設計:方法、趨勢與挑戰
- Expert Data Visualization
- RSpec Essentials
- 微服務架構深度解析:原理、實踐與進階
- Learning Continuous Integration with TeamCity
- GameMaker Essentials
- 開源項目成功之道
- 從零開始:UI圖標設計與制作(第3版)
- Vue.js 3應用開發與核心源碼解析
- INSTANT JQuery Flot Visual Data Analysis
- Selenium WebDriver Practical Guide