1. 變量分類
- 從變量的作用域
- 全局變量
在函數外部定義的變量被稱作外部變量或全局變量。 - 局部變量
在函數內部定義的變量,只在本函數內部有效。
- 全局變量
- 從變量的存儲時間(生存週期)
- 靜態存儲方式
程序運行期間固定分配的存儲空間。 - 動態存儲方式
程序運行期間動態分配的存儲空間。
- 靜態存儲方式
2. 內存分區
參考《Windows內存管理》
全局變量,靜態變量都存儲在“靜態存儲區”;
函數的形式參數,自動變量(未加 static 聲明的局部變量),函數調用時的現場保護和返回地址,這些都存儲在“動態存儲區”。
在 c 語言中,每一個變量和函數都有兩個屬性:數據類型和數據的存儲類別。
數據類型:字符型,整型,浮點型等
存儲類別:靜態存儲和動態存儲。
對變量的聲明有四種基本的類型: auto 變量,static 變量,register 變量,extern 變量。
3. auto 變量
函數中的局部變量,如果不專門聲明爲 static
存儲類別,那麼都是動態分配存儲空間。
關鍵字 auto
可以省略,如果不寫,都隱含確定爲“動態存儲類別”。
int fx(int a)
{
auto int b, c = 3; // 等價於 int b, c = 3;
...
}
執行完 fx 函數後,a,b,c 所在的存儲單元自動釋放。
4. static 聲明局部變量
用static 申請的局部變量在函數抵用結束時不消失,而是保留原值,下一次調用時,該變量值依然保持。
#include <iostream>
void FileOneFxOne()
{
int iA = 0;
static int iStatic = 1;
iA++;
iStatic++;
std::cout << "局部變量 iA = " << iA << std::endl;
std::cout << "局部靜態變量 iStatic = " << iStatic << std::endl;
}
int main()
{
std::cout << "第一次調用:" << std::endl;
FileOneFxOne();
std::cout << "\n第二次調用:" << std::endl;
FileOneFxOne();
return 0;
}
第幾次調用 | 起始 | 結束 |
---|---|---|
第一次調用 | iA = 0; iStatic = 1 | iA = 1; iStatic = 2 |
第二次調用 | iA = 0; iStatic = 2 | iA = 1; iStatic = 3 |
第三次調用 | iA = 0; iStatic = 3 | iA = 1; iStatic = 4 |
5. register 變量
一般情況,變量都存在內存中,c 語言允許將局部變量的值放在 CPU 的寄存器中,寄存器的存取速度遠遠大於內存的存取速度。
void fx()
{
register int i;
...
}
只有局部自動變量和形參可以作爲寄存器變量,局部靜態變量不能作爲寄存器變量。
當今的優化編譯器可以自動識別使用頻繁的變量,從而自動將這些變量放在寄存器中。
6. 用 extern 聲明外部變量
用 extern
來聲明外部變量,是爲了擴展外部變量的作用域。
int main()
{
extern A;
A++;
...
}
int A = 0;
int fx()
{
...
}
由於 全局變量 A 定義在 mian 函數之後,所以如果不使用 extern 關鍵字,編譯器將報錯。
extern 也可以將全局變量的範圍擴展到同一源程序的不同文件之中,如下所示:
- file1.cpp
#include <iostream>
#include "FileTwo.h"
int iGlobal = 3;
int main()
{
std::cout << "main : iGobal = " << iGlobal << std::endl;
FileTwo();
std::cout << "main : iGobal = " << iGlobal << std::endl;
FileTwo();
return 0;
}
- file2.cpp
#include "FileTwo.h"
#include <iostream>
extern int iGlobal;
void FileTwo()
{
iGlobal++;
std::cout << "FileTwo : iGlobal = " << iGlobal << std::endl;
}
- file2.cpp 頭文件
#ifndef FILETWO_H
#define FILETWO_H
void FileTwo();
#endif
輸出結果
main : iGobal = 3
FileTwo : iGlobal = 4
main : iGobal = 4
FileTwo : iGlobal = 5
在一個文件中定義的外部變量,在另一個文件中通過 extern 來聲明。
7. 內部函數和外部函數
內部函數:只能被文本中其他函數調用。如:
static int fx();
static
使其局部化,不能被其他文件引用。
外部函數:在函數的最左端加上關鍵字 extern
,則表示可以被其他函數調用,如:
extern int fx();
c語言中規定,如果在定義函數時省略 extern
,則隱含爲外部函數,在需要調用此函數的文件中,用extern
對函數做聲明。
8. static 的全局與局部
全局變量:
- 普通全局變量:作用域是整個源程序,在同一源文件的不同文件中可見
- static 全局變量:作用域是所在的源文件,只能被定義該變量的文件中可見
局部變量:
- 普通局部變量:
運行時賦值
,每調用一次賦一次值,調用結束自動釋放。 - static 局部變量:
程序編譯時賦值
,只初始化一次,函數調用結束其值依然存在,不釋放。
函數:
- 普通函數:可以被同一源程序中的其他函數調用。
- static 靜態函數:只在定義該函數的文件中可見,不能被源程序中的其他文件使用。
9. 參考
《c程序設計》第三版