2018-04-28-c-storage-type

title layout categories excerpt tags
C語言之變量存儲類型與鏈接屬性
post
C語言
C語言的變量存儲類型與鏈接屬性的區別分析
存儲類型 鏈接屬性 靜態變量static extern 寄存器

C語言中一個重要的東西就是弄清申明變量的類型、作用域、存儲類型、鏈接屬性等,例如是整型還是浮點型,存儲於普通內存還是堆棧或者寄存器,作用於全局還是局部,能否被其他文件 引用等。

鏈接屬性

申明變量或函數時需要標識符,標識符的鏈接屬性一共有三種:external(外部), internal(內部), none(無),external和internal常用,none表示無鏈接屬性,該標識符的多個申明被當成獨立不同的實體。

顧名思義,external表示能被其它源文件訪問的變量或函數,internal則不能被其它源文件訪問,並且缺省情況下代碼塊(block)外部的變量爲external屬性,也就是外部變量,代碼塊內部的變量爲internal屬性,即局部變量.

如果需要改變鏈接屬性需要使用 externstatic 關鍵字,extern 是轉化爲external屬性,static 是轉化爲internal屬性。 舉例說明:

#include<stdio.h>
int a = 1;              /* 這裏是代碼塊外部,external 屬性,缺省爲"extern" */
extern int aa = 11;     /* 與上面效果一樣 */
static int aaa = 111;   /* 這裏申明的是 internal 屬性,不能被其它源文件訪問 */
void example()          /* 這裏申明的 example() 函數也是external屬性,能被其它源文件訪問 */
{
	int b = 2;          /* 這裏是代碼塊內部,internal 屬性 */
	extern int bb = 22; /* 這裏的意思是訪問其它源文件的全局變量 */
}

注意上面指出的代碼塊內部和外部,定義的函數的花括號之外叫做代碼塊外部,之內叫做代碼塊內部。 代碼塊外部缺省爲extern,並且代碼塊外部使用extern表示被其它源文件訪問,代碼塊內部使用extern表示訪問其它文件的外部變量。

存儲類型

存儲類型指申明的變量將被存儲到什麼地方去,並且與其存儲週期有關,就是這個變量何時被創建,何時被銷燬,保持多久。

存儲類型有三種: 靜態變量(static) ---> 存儲於普通內存。 自動變量(auto) ---> 存儲於堆棧。 寄存器變量(register) ---> 存儲於寄存器。

靜態變量

任何代碼塊之外定義的變量,總是處於靜態內存中,無需使用 static 關鍵字,在程序運行之前創建,程序整個執行期間始終存在

自動變量

代碼塊內部申明的變量,並且缺省情況下都是(auto)類型,所以很少使用,存儲於堆棧中,程序執行到申明變量處被創建,離開後被銷燬,每次在堆棧中佔據的內存位置都可能不同

寄存器變量

用於申明自動變量,即在代碼塊內部使用,使這類變量存儲於寄存器中,寄存器中的變量比內存中的變量訪問效率更高。 但是,如果有太多變量申明爲 register ,只會選取前幾個存儲於寄存器中,其它處理爲普通自動變量。

通常把使用頻率最高的變量申明爲寄存器變量,或者指針申明爲寄存器變量,以提高效率。例如可以把函數的形參申明爲寄存器變量(有可能它節省的時間空間開銷抵不上覆制這幾個值的開銷)。

綜合舉例
#include<stdio.h>
int a = 1;                  /* 靜態變量(static),這裏不能使用 register */
int main()
{
	int b = 2;              /* 自動變量,省略 auto */
	register int c = 3;     /* 寄存器變量(register) */
	int aaa(register int d) /* 申明函數形參爲 register */
	static int e = 4;       /* 申明靜態變量,和變量 b 一個屬性 */ 
}
初始化

靜態變量在不指定初始值的時候,初始化爲 0; 自動變量是否初始化賦值,並無效率的改變(每次執行都要重新初始化),這也是它的優點:可以用任何“表達式”作爲初始值。例如:

int add(int a)
{
	int b = a + 1;      /* 將表達式 a + 1 的值初始化給 b */
	return b;
}

注意

  • static 申明函數或代碼塊之外的變量時,只修改鏈接屬性 ``externalinternal`,存儲類型作用域不變。
  • static 申明代碼塊內部變量時,將自動變量修改爲靜態變量,但是鏈接屬性作用域不變。
綜合舉例
#include<stdio.h>
int a = 1;             /* 鏈接屬性爲 external,缺省 extern */
static int b = 2;      /* 修改連接屬性爲靜態變量,不能被其它源文件訪問,依然爲全局變量,存儲於靜態內存中 */
int main()
{
	int c = 3;         /* 自動變量,存儲到堆棧 */
	static int d = 4;  /* 靜態變量,存儲到普通內存,依然不能被其它源文件訪問 */
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章