static、const、extern關鍵字的詳解

一、static關鍵字

1.局部變量中的static

       普通局部變量就是在函數內部定義的變量(不加static修飾符)。編譯器一般不對普通局部變量進行初始化,它的值在初始時是不確定的,除非對其顯式賦值。普通的局部變量在棧空間上分配,這個局部變量所在的函數被多次調用時,每次調用這個局部變量在棧上的位置都不一定相同。局部變量也可以在堆上動態分配,但是記得使用完這個堆空間後要釋放之。

       static局部變量叫靜態局部變量。它與普通的局部變量的區別

           1)位置:靜態局部變量被編譯器放在全局存儲區,在程序的整個生命週期中存在。

           2)訪問權限:靜態局部變量只能被其作用域內的變量或函數訪問。也就是說雖然它會在程序的整個生命週期中存在,由於它是static的,它不能被其他的函數和源文件訪問。

           3)值:靜態局部變量如果沒有被用戶初始化,則會被編譯器自動賦值爲0,且只初始化一次,以後每次調用靜態局部變量的時候都用上次調用後的值,可以參考下面的示例

#include <stdio.h>
//局部變量static的作用
void func(void)
{
	int n = 10;
	n++;
	printf("%d%s", n," ");
}

void func_static(void)
{
	static int n = 10;
	n++;
	printf("%d%s", n, " ");
}

int main(void)
{
	for (int i = 0; i < 5; i++) {
		func();
	}
	printf("\n");

	for (int i = 0; i < 5; i++) {
		func_static();
	}
	system("pause");
	return 0;
}

輸出的結果是:


2.全局變量中的static

static修飾全局變量的時候,這個全局變量只能在本文件中訪問,不能在其它文件中訪問,即便是extern外部聲明也不可以。 

3.函數中的static

static修飾一個函數,則這個函數的只能在本文件中調用,不能被其他文件調用。

4.作用場合

(1)不想被釋放的時候,可以使用static修飾。比如修飾函數中存放在棧空間的數組。如果不想讓這個數組在函數調用結束釋放可以使用static修飾 
(2)考慮到數據安全性(全程想要使用全局變量的時候應該先考慮使用static)

 

5.面向對象(C++)中的static

可參考https://blog.csdn.net/computer_liuyun/article/details/29235111這篇文章的詳細解答
靜態數據成員 
(1)靜態數據成員可以實現多個對象之間的數據共享,它是類的所有對象的共享成員,它在內存中只佔一份空間,如果改變它的值,則各對象中這個數據成員的值都被改變。 
(2)靜態數據成員是在程序開始運行時被分配空間,到程序結束之後才釋放,只要類中指定了靜態數據成員,即使不定義對象,也會爲靜態數據成員分配空間。 
(3)靜態數據成員可以被初始化,但是只能在類體外進行初始化,若爲對靜態數據成員賦初值,則編譯器會自動爲其初始化爲0 


(4)靜態數據成員既可以通過對象名引用,也可以通過類名引用。

靜態成員函數 
(1)靜態成員函數和靜態數據成員一樣,他們都屬於類的靜態成員,而不是對象成員。 
(2)非靜態成員函數有this指針,而靜態成員函數沒有this指針。 
(3)靜態成員函數主要用來訪問靜態數據成員而不能訪問非靜態成員。

 

二、const關鍵字

1.修飾局部變量

const int n=1;
int const n=1;

上面兩種寫法都可以,值得注意的是:

  • const聲明的變量只能被讀
  • 必須初始化

2.修飾常量字符串

const char* str="fsadsadsa";

const修飾常量靜態字符串,位於只讀內存區域,不能對字符串進行修改eg:str[2]='a'是錯誤的。

3.修飾指針

1)常量指針(是指針指向的內容是常量,不能通過常量指針改變變量的值,僅此而已)

const int * n;
int const * n;
  • 常量指針說的是不能通過這個指針改變變量的值,但是還是可以通過其他的引用來改變變量的值的。
  • 常量指針指向的值不能改變,但是這並不是意味着指針本身不能改變,常量指針可以指向其他的地址。

2)指針常量(指針本身是個常量,不能再指向其他的地址,僅此而已)

int *const n;
  • 指針常量指向的地址不能改變,但是地址中保存的數值是可以改變的,可以通過其他指向改地址的指針來修改。

3)指向常量的常指針

指針指向的位置不能改變並且也不能通過這個指針改變變量的值,但是依然可以通過其他的普通指針改變變量的值。

const int* const p;

4.修飾函數

1)修飾函數參數

  • 防止修改指針指向的內容
void func(const int *p)
  • 防止修改指針指向的地址
void func( int* const p)
  • 以上兩種的結合。

2)修飾函數的返回值

當const修飾函數的返回值時,且指針傳遞方式的函數返回值加 const 修飾,那麼該返回值只能被賦給加const 修飾的同類型指針。 

5.修飾全局變量

       全局變量的作用域是整個文件,一旦有一個函數改變了全局變量的值,它也會影響到其他引用這個變量的函數,導致除了bug後很難發現,如果一定要用全局變量,我們應該儘量的使用const修飾符進行修飾,這樣防止不必要的人爲修改,使用的方法與局部變量是相同的。

 

三、extern關鍵字

        可置於變量或者函數前,以表示變量或者函數的定義在別的文件中。提示編譯器遇到此變量或函數時,在其它模塊中尋找其定義

  • 函數的聲明extern關鍵詞是可有可無的,因爲函數本身不加修飾的話就是extern的。
  • 全局變量在外部使用聲明時,extern關鍵詞是必須的,如果變量無extern修飾且沒有顯式的初始化,同樣成爲變量的定義,因此此時必須加extern,而編譯器在此標記存儲空間在執行時加載如內存並初始化爲0。
  • 局部變量的聲明不能有extern的修飾,且局部變量在運行時纔在堆棧部分分配內存。
  • 注意定義只有一次,聲明可以有多次。

extern int a;//聲明一個全局變量a

int a; //定義一個全局變量a

extern int a =0 ;//定義一個全局變量a 並給初值。

int a =0;//定義一個全局變量a,並給初值,

第四個等於第 三個,都是定義一個可以被外部使用的全局變量,並給初值。定義只能出現在一處。也就是說,不管是int a;還是extern int a=0;還是int a=0;都只能出現一次,而那個extern int a可以出現很多次。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章