淺談C語言變數
王佰營 徐麗紅
任何一種程式語言都離不開變數,特別是資料處理型程式,變數的使用非常頻繁,沒有變數參與程式甚至無法編制,即使編制執行後的意義也不大。變數之所以重要,是因為變數是程式語言中資料的符號標識和載體。
C語言是一種應用廣泛的善於實現控制的語言,變數在C語言中的應用更是靈活多變。那麼變數究竟是什麼呢?變數是記憶體或暫存器中用一個識別符號命名的儲存單元,可以用來儲存一個特定型別的資料,並且資料的值在程式執行過程中可以進行修改。可見,變數首先是一個識別符號或者名稱,就像一個客房的編號一樣,有了這個編號我們在交流中就可方便言表,否則,我們只可意會,那多不方便。為了方便,我們在給變數命名時,最好能符合大多數人的習慣,基本可以望名知義,便於交流和維護;其次,變數是唯一確定的對應記憶體若干儲存單元或者某個暫存器。這些是編譯器來保證的,使用者一般不用費心。
程式設計師一旦定義了變數,那麼,變數就至少可為我們提供兩個資訊:一是變數的地址,即就是,作業系統為變數在記憶體中分配的若干記憶體的首地址;二是變數的值,也就是,變數在記憶體中所分配的那些記憶體單元中所存放的資料。
由於程式的多樣需要,我們對變數也有各種各樣的要求,比如:變數的生命期,變數的初始狀態,變數的有效區域,變數的開闢地和變數的開闢區域的大小等等;為了滿足這些要求,C語言的發明者就設定了以下變數:
1、 不同資料型別的變數;如:char cHar, int iTimes, flaot faverage;
2、 全域性變數或者叫全程變數;
3、 區域性變數;
4、 靜態變數: 靜態全域性變數和靜態區域性變數;關鍵詞:static
5、 暫存器變數;關鍵詞:register;
6、 外部變數: 關鍵詞:extern;
C語言中,變數在記憶體中開闢地的大小由資料型別決定的,由於PC機中規定一個地址單元存一個位元組,不同的資料型別的變數,為其分配的地址單元數是不一樣的。C語言中除幾種基本的資料型別外使用者還可以自己定義所需要的資料型別:
1、 bool型 sizeof(bool): 1
2、 char型: sizeof(char): 1
3、 short型: sizeof(short): 2
4、 int型: sizeof(int): 4
5、 long型: sizeof(long): 4
6、 float型: sizeof(float): 4
7、 double型: sizeof(double): 8
8、 自定義型:如:
typedef struct tagMyData
{
char cHar;
int iTimes;
float faverage;
}MyDatap;
sizeof(MyDatap): 12
char szBuf[]="HELLO C&C++!";
sizeof(szBuf): 13
區域性變數和全域性變數是相對而言的;如下:區域性變數 int itmp;
int Get_Max( const int& x, const int& y, const int& z )
int itmp;
if(x > y) itmp = x;
else itmp = y;
if( itmp > z ) return itmp;
else return z;
}
在函式內部說明的變數為區域性變數,只有在函式執行時,區域性變數才存在,當函式執行完退出後,區域性變數隨之消失。也就是,當函式執行完退出後,原先在函式內定義的變數現在不能用,這通常由編譯器保證,它會阻止編譯透過。也就是說,原來為那個區域性變數分配的記憶體,現在已經不屬於它,它再無權訪問了。如要再使用這些記憶體單元就必須從新定義變數來申請,只有分配給的變數才可訪問它。否則,就會出錯,如陣列越界訪問。
與區域性變數不同,全域性變數在整個程式都是可見的,可在整個程式執行過程中,對於任何一個程式都是可用的。全域性變數的說明的位置在所有函式之外,但可被任何一個函式使用,讀取或者寫入。如下:全域性變數 int iCount, bool bForward;
int iCount; //全域性變數;
bool bForward; //全域性變數;
void add( void );
void dec( void );
void man(void )
while( iCount < 1000 && iCount > -1000)
add( );
dec( );
printf("COUNT:%d;\n", iCount)
void add( void )
if( bForward ) iCount++;
void dec( void )
if(!bForward ) iCount--;
可見,全域性變數非常方便不同函式間資料共享,同樣,任何函式在在使用資料時,都不敢保證資料是否已被修改。如果程式設計師無法保證這個,就儘量避免使用全域性變數。
靜態變數是分配在儲存器中C程式所佔據的資料段內, C程式執行的整個過程中一直保留,不會被別的變數佔用。靜態變數可以定義成全域性變數或區域性變數,當定義為全域性變數時,在它定義的程式的整個執行期間均存在並且保持原來的儲存單元位置不會改變。那麼既然有了全域性變數為什麼還要定義全域性靜態變數呢?看下邊的示例:
模組1:
int a;
static int b;
void fun1( void )
……
fun2( );
模組2:
extern int a;
satic int b;
void fun2( void )
fun1( );
分別編譯,然後連結兩個模組。。。。。。
模組1和模組2中,變數a為同一個變數;而變數b就不是同一個變數!雖然它們的的資料型別和名稱均相同;就是因為有static;原因是,如果在全域性變數說明前加上靜態變數說明符static,它就會通知編譯器該全域性變數只在被定義的這個檔案或模組中可見的。就是說,該靜態全域性變數在其他檔案中是不可見的,在其他檔案中的程式是不允許訪問的。這在一定程度上減少了全域性變數的副作用的影響。
同靜態全域性變數定義一樣,當在區域性變數名前加靜態變數說明符static,該變數就定義為靜態區域性變數。編譯器為該變數建立永久儲存單元。永久是指C程式執行的整個過程中一直保留,不會被別的變數佔用。靜態區域性變數和靜態全域性變數的根本區別在作用區域上,靜態區域性變數只在它被說明的函式或複合語句中有效,並且在兩次函式呼叫期間仍然儲存其值不變,即就是有記憶功能;它們的生命期是相同的,和C程式整個執行期同在。如下例:
#include "stdafx.h"
void counts(void);
void countd(void);
int main(int argc, char* argv[])
int i = 0;
while( i++<10)
counts( ); //使用靜態區域性變數
i = 0;
countd( ); //使用區域性變數
return 0;
void counts(void) //使用靜態區域性變數
static int isc ; //未賦初值;
isc++;
printf("dsc = %d;\n", dsc);
void countd(void) //使用區域性變數
int idc = 0;
idd++;
printf("idc=%d;\n",idc);
執行結果為:
isc = 1; //使用靜態區域性變數
isc = 2;
isc = 3;
isc = 4;
isc = 5;
isc = 6;
isc = 7;
isc = 8;
isc = 9;
isc = 10;
idc = 1; //使用區域性變數
idc = 1;
透過以上程式你也看得出:
1、 區域性變數和靜態區域性變數的區別:記憶功能;
2、 靜態區域性變數只初始化一次,並且預設初始化為0;
靜態變數在定義時若未被賦值,則編譯程式將其初始化為0;
暫存器變數不像其他變數那樣在記憶體中存放資料,而是在CPU的暫存器中暫存資料,使用暫存器變數比使用記憶體變數的操作速度快得多。只有整型和字元型變數可定義為暫存器變數。定義方式如下:
register int iTemp;
由於CPU中暫存器有限,儘量減少使用數量和和佔用時間,用完馬上釋放;不能定義為全域性變數,也不能定義在結構或者類中。
為了大型程式的管理,將一個大型的程式分成若干個獨立的模組和檔案分別編譯,然後統一連結在一起。為了解決全域性變數和函式的共用問題,就引入了extern關鍵字。這樣只需在一個檔案中定義全域性變數和函式,在另一個檔案中要用到這些變數和函式時,只需將那個檔案中的變數和函式說明表複製過來,在前面加上extern,告訴編譯器,這些變數和函式已經在別的檔案中定義說明,在此不必再定義說明了。
淺談C語言變數
王佰營 徐麗紅
任何一種程式語言都離不開變數,特別是資料處理型程式,變數的使用非常頻繁,沒有變數參與程式甚至無法編制,即使編制執行後的意義也不大。變數之所以重要,是因為變數是程式語言中資料的符號標識和載體。
C語言是一種應用廣泛的善於實現控制的語言,變數在C語言中的應用更是靈活多變。那麼變數究竟是什麼呢?變數是記憶體或暫存器中用一個識別符號命名的儲存單元,可以用來儲存一個特定型別的資料,並且資料的值在程式執行過程中可以進行修改。可見,變數首先是一個識別符號或者名稱,就像一個客房的編號一樣,有了這個編號我們在交流中就可方便言表,否則,我們只可意會,那多不方便。為了方便,我們在給變數命名時,最好能符合大多數人的習慣,基本可以望名知義,便於交流和維護;其次,變數是唯一確定的對應記憶體若干儲存單元或者某個暫存器。這些是編譯器來保證的,使用者一般不用費心。
程式設計師一旦定義了變數,那麼,變數就至少可為我們提供兩個資訊:一是變數的地址,即就是,作業系統為變數在記憶體中分配的若干記憶體的首地址;二是變數的值,也就是,變數在記憶體中所分配的那些記憶體單元中所存放的資料。
由於程式的多樣需要,我們對變數也有各種各樣的要求,比如:變數的生命期,變數的初始狀態,變數的有效區域,變數的開闢地和變數的開闢區域的大小等等;為了滿足這些要求,C語言的發明者就設定了以下變數:
1、 不同資料型別的變數;如:char cHar, int iTimes, flaot faverage;
2、 全域性變數或者叫全程變數;
3、 區域性變數;
4、 靜態變數: 靜態全域性變數和靜態區域性變數;關鍵詞:static
5、 暫存器變數;關鍵詞:register;
6、 外部變數: 關鍵詞:extern;
C語言中,變數在記憶體中開闢地的大小由資料型別決定的,由於PC機中規定一個地址單元存一個位元組,不同的資料型別的變數,為其分配的地址單元數是不一樣的。C語言中除幾種基本的資料型別外使用者還可以自己定義所需要的資料型別:
1、 bool型 sizeof(bool): 1
2、 char型: sizeof(char): 1
3、 short型: sizeof(short): 2
4、 int型: sizeof(int): 4
5、 long型: sizeof(long): 4
6、 float型: sizeof(float): 4
7、 double型: sizeof(double): 8
8、 自定義型:如:
typedef struct tagMyData
{
char cHar;
int iTimes;
float faverage;
}MyDatap;
sizeof(MyDatap): 12
char szBuf[]="HELLO C&C++!";
sizeof(szBuf): 13
區域性變數和全域性變數是相對而言的;如下:區域性變數 int itmp;
int Get_Max( const int& x, const int& y, const int& z )
{
int itmp;
if(x > y) itmp = x;
else itmp = y;
if( itmp > z ) return itmp;
else return z;
}
在函式內部說明的變數為區域性變數,只有在函式執行時,區域性變數才存在,當函式執行完退出後,區域性變數隨之消失。也就是,當函式執行完退出後,原先在函式內定義的變數現在不能用,這通常由編譯器保證,它會阻止編譯透過。也就是說,原來為那個區域性變數分配的記憶體,現在已經不屬於它,它再無權訪問了。如要再使用這些記憶體單元就必須從新定義變數來申請,只有分配給的變數才可訪問它。否則,就會出錯,如陣列越界訪問。
與區域性變數不同,全域性變數在整個程式都是可見的,可在整個程式執行過程中,對於任何一個程式都是可用的。全域性變數的說明的位置在所有函式之外,但可被任何一個函式使用,讀取或者寫入。如下:全域性變數 int iCount, bool bForward;
int iCount; //全域性變數;
bool bForward; //全域性變數;
void add( void );
void dec( void );
void man(void )
{
while( iCount < 1000 && iCount > -1000)
{
add( );
dec( );
printf("COUNT:%d;\n", iCount)
}
}
void add( void )
{
if( bForward ) iCount++;
}
void dec( void )
{
if(!bForward ) iCount--;
}
可見,全域性變數非常方便不同函式間資料共享,同樣,任何函式在在使用資料時,都不敢保證資料是否已被修改。如果程式設計師無法保證這個,就儘量避免使用全域性變數。
靜態變數是分配在儲存器中C程式所佔據的資料段內, C程式執行的整個過程中一直保留,不會被別的變數佔用。靜態變數可以定義成全域性變數或區域性變數,當定義為全域性變數時,在它定義的程式的整個執行期間均存在並且保持原來的儲存單元位置不會改變。那麼既然有了全域性變數為什麼還要定義全域性靜態變數呢?看下邊的示例:
模組1:
int a;
static int b;
void fun1( void )
{
……
fun2( );
……
}
模組2:
extern int a;
satic int b;
void fun2( void )
{
……
fun1( );
……
}
分別編譯,然後連結兩個模組。。。。。。
模組1和模組2中,變數a為同一個變數;而變數b就不是同一個變數!雖然它們的的資料型別和名稱均相同;就是因為有static;原因是,如果在全域性變數說明前加上靜態變數說明符static,它就會通知編譯器該全域性變數只在被定義的這個檔案或模組中可見的。就是說,該靜態全域性變數在其他檔案中是不可見的,在其他檔案中的程式是不允許訪問的。這在一定程度上減少了全域性變數的副作用的影響。
同靜態全域性變數定義一樣,當在區域性變數名前加靜態變數說明符static,該變數就定義為靜態區域性變數。編譯器為該變數建立永久儲存單元。永久是指C程式執行的整個過程中一直保留,不會被別的變數佔用。靜態區域性變數和靜態全域性變數的根本區別在作用區域上,靜態區域性變數只在它被說明的函式或複合語句中有效,並且在兩次函式呼叫期間仍然儲存其值不變,即就是有記憶功能;它們的生命期是相同的,和C程式整個執行期同在。如下例:
#include "stdafx.h"
void counts(void);
void countd(void);
int main(int argc, char* argv[])
{
int i = 0;
while( i++<10)
{
counts( ); //使用靜態區域性變數
}
i = 0;
while( i++<10)
{
countd( ); //使用區域性變數
}
return 0;
}
void counts(void) //使用靜態區域性變數
{
static int isc ; //未賦初值;
isc++;
printf("dsc = %d;\n", dsc);
}
void countd(void) //使用區域性變數
{
int idc = 0;
idd++;
printf("idc=%d;\n",idc);
}
執行結果為:
isc = 1; //使用靜態區域性變數
isc = 2;
isc = 3;
isc = 4;
isc = 5;
isc = 6;
isc = 7;
isc = 8;
isc = 9;
isc = 10;
idc = 1; //使用區域性變數
idc = 1;
idc = 1;
idc = 1;
idc = 1;
idc = 1;
idc = 1;
idc = 1;
idc = 1;
idc = 1;
透過以上程式你也看得出:
1、 區域性變數和靜態區域性變數的區別:記憶功能;
2、 靜態區域性變數只初始化一次,並且預設初始化為0;
靜態變數在定義時若未被賦值,則編譯程式將其初始化為0;
暫存器變數不像其他變數那樣在記憶體中存放資料,而是在CPU的暫存器中暫存資料,使用暫存器變數比使用記憶體變數的操作速度快得多。只有整型和字元型變數可定義為暫存器變數。定義方式如下:
register int iTemp;
由於CPU中暫存器有限,儘量減少使用數量和和佔用時間,用完馬上釋放;不能定義為全域性變數,也不能定義在結構或者類中。
為了大型程式的管理,將一個大型的程式分成若干個獨立的模組和檔案分別編譯,然後統一連結在一起。為了解決全域性變數和函式的共用問題,就引入了extern關鍵字。這樣只需在一個檔案中定義全域性變數和函式,在另一個檔案中要用到這些變數和函式時,只需將那個檔案中的變數和函式說明表複製過來,在前面加上extern,告訴編譯器,這些變數和函式已經在別的檔案中定義說明,在此不必再定義說明了。