static 變量 做用域 全局變量 局部變量 外部變量 常量 volatile變量

做用域 全局變量 局部變量 靜態變量 外部變量 常量 volatile變量html

做用域:ios

做用域規則告訴咱們一個變量的有效範圍,它在哪兒建立,在哪兒銷燬(也就是說超出了做用域)。變量的有效做用域從它的定義點開始,到和定義變量以前最鄰近的開括號配對的第一個閉括號。也就是說,做用域由變量所在的最近一對括號肯定。程序員

全局變量:數組

全局變量是在全部函數體的外部定義的,程序的所在部分(甚至其它文件中的代碼)均可以使用。全局變量不受做用域的影響,問題可使用的(也就是說,全局變量的生命期一直到程序的結束)。若是在一個文件中使用extern關鍵字來聲明另外一個文件中存在的全局變量,那麼這個文件可使用這個數據。函數

局部變量:post

局部變量出如今一個做用域內,它們是侷限於一個函數的。局部變量常常被稱爲自動變量,由於它們在進入做用域時自動生成,離開做用域時自動消失。關鍵字auto能夠顯式地說明這個問題,可是局部變量默認爲優化

auto,因此沒有必要聲明爲autospa

寄存器變量設計

寄存器變量是一種局部變量。關鍵字register告訴編譯器儘量快地訪問這個變量。加快訪問速度取決於現實,可是,正如名字所暗示的那樣,這常常是經過在寄存器中放置變量來作到的。這並不能保證將變置在寄存器中,甚至也不能保證提升訪問速度。這只是對編譯器的一個暗示。指針

使用register變量是有限制的。不可能獲得或計算register 變量的地址。register變量只能在一個塊中聲明(不可能有全局的或靜態的register變量)。然而能夠在一個函數中(即在參數表中)使用register變量做爲一個形式參數。

通常地,不該當推測編譯器的優化器,由於它可能比咱們作得更好。所以,最好避免使用關鍵字register

靜態變量

關鍵字static有一些獨特的意義。一般,函數中定義局部變量在函數中做用域結束時消失。當再次調用這個函數時,會從新建立變量的存儲空間,其值會被從新初始化。若是想使局部變量的值在程序的整個生命期裏仍然存在,咱們能夠定義函數的局部變量爲static(靜態的),並給它一個初始化。初始化只在函數第一次調用時執行,函數調用之間變量的值保持不變,這種方式,函數能夠記住函數調用之間的一些信息片段。

咱們可能奇怪爲何不使用全局變量。static變量的優勢是在函數範圍以外它是不可用的,因此它不可能被輕易改變。這會使錯誤局部化。

外部變量

extern告訴編譯器存在着一個變量和函數,即便編譯器在當前的文件中沒有看到它。這個變量或函數可能在一個文件或者在當前文件的後面定義。例如extern int i;編譯器會知道i確定做爲全局變量存在於某處。當編譯器看到變量i的定義時,並無看到別的聲明,因此知道它在文件的前面已經找到了一樣聲明的i

常量

const告訴編譯器這個名字表示常量,無論是內部的仍是用戶定義的數據類型均可以定義爲const。若是定義了某對象爲常量,而後試圖改變它,編譯器將會產生錯誤。在C++中一個const必須有初始值。

volatile變量

限定詞const告訴編譯器這是不會改變的(這就是容許編譯器執行額外的優化);而限定詞volatile則告訴編譯器不知道什麼時候變化,防止編譯器依據變量的穩定性做任何優化。

參考《Thinking in C++》第一卷第三章

 ——————————————————————————————————————

Static 做用詳述

1.先來介紹它的第一條也是最重要的一條:隱藏

     當咱們同時編譯多個文件時,全部未加static前綴的全局變量和函數都具備全局可見性。爲理解這句話,我舉例來講明。咱們要同時編譯兩個源文件,一個是a.c,另外一個是main.c.

下面是a.c的內容:

char a = 'A'; // global variable
void msg()
{
printf("Hello\n");
}

下面是main.c的內容:

int main(void)
{
extern char a; // extern variable must be declared before use
printf("%c ", a);
(void)msg();
return 0;
}

程序的運行結果是:

A Hello

     你可能會問:爲何在a.c中定義的全局變量a和函數msg能在main.c中使用?前面說過,全部未加static前綴的全局變量和函數都具備全局可見 性,其它的源文件也能訪問。此例中,a是全局變量,msg是函數,而且都沒有加static前綴,所以對於另外的源文件main.c是可見的。

若是加了static,就會對其它源文件隱藏。例如在a和msg的定義前加上 static,main.c就看不到它們了。利用這一特性能夠在不一樣的文件中定義同名函數和同名變量,而沒必要擔憂命名衝突。Static能夠用做函數和變 量的前綴,對於函數來說,static的做用僅限於隱藏,而對於變量,static還有下面兩個做用。

2. static的第二個做用是保持變量內容的持久

     存儲在靜態數據區的變量會在程序剛開始運行時就完成初始化,也是惟一的一次初始化。共有兩種變量存儲在靜態存儲區:全局變量和static變量,只不過和 全局變量比起來,static能夠控制變量的可見範圍,說到底static仍是用來隱藏的。雖然這種用法不常見,但我仍是舉一個例子。

#include <stdio.h>
int fun(void){
static int count = 10; // 事實上此賦值語句歷來沒有執行過
return count--;
}
int count = 1;
int main(void)
{
printf("global\t\tlocal static\n");
for(; count <= 10; ++count)
printf("%d\t\t%d\n", count, fun());
return 0;
}

程序的運行結果是:

global local static
1  10
2   9
3   8
4   7
5   6
6   5
7   4
8   3
9   2
10  1

3. static的第三個做用是默認初始化爲0.其實全局變量也具有這一屬性,由於全局變量也存儲在靜態數據區

     在靜態 數據區,內存中全部的字節默認值都是0x00,某些時候這一特色能夠減小程序員的工做量。好比初始化一個稀疏矩陣,咱們能夠一個一個地把全部元素都置0, 而後把不是0的幾個元素賦值。若是定義成靜態的,就省去了一開始置0的操做。再好比要把一個字符數組當字符串來用,但又以爲每次在字符數組末尾加‘\0’ 太麻煩。若是把字符串定義成靜態的,就省去了這個麻煩,由於那裏原本就是‘\0’。不妨作個小實驗驗證一下。

#include <stdio.h>
int a;
int main(void)
{
int i;
static char str[10];
printf("integer: %d; string: (begin)%s(end)", a, str);
return 0;
}

程序的運行結果以下integer: 0; string: (begin)(end)

最後對static的三條做用作一句話總結。首先static的最主要功能是隱藏,其次由於static變量存放在靜態存儲區,因此它具有持久性和默認值0.

4. 用static聲明的函數和變量小結

static 聲明的變量在C語言中有兩方面的特徵:

 

 

1)、變量會被放在程序的全局存儲區中,這樣能夠在下一次調用的時候還能夠保持原來的賦值。這一點是它與堆棧變量和堆變量的區別。
2)、變量用static告知編譯器,本身僅僅在變量的做用範圍內可見。這一點是它與全局變量的區別。

 
Tips:
A.若全局變量僅在單個C文件中訪問,則能夠將這個變量修改成靜態全局變量,以下降模塊間的耦合度;
B.若全局變量僅由單個函數訪問,則能夠將這個變量改成該函數的靜態局部變量,以下降模塊間的耦合度;
C.設計和使用訪問動態全局變量、靜態全局變量、靜態局部變量的函數時,須要考慮重入問題;
    D.
若是咱們須要一個可重入的函數,那麼,咱們必定要避免函數中使用static變量(這樣的函數被稱爲:帶內部存儲器功能的的函數)
      E.
函數中必需要使用static變量狀況:好比當某函數的返回值爲指針類型時,則必須是static的局部變量的地址做爲返回值,若爲auto類型,則返回爲錯指針。

    函數前加static使得函數成爲靜態函數。但此處「static」的含義不是指存儲方式,而是指對函數的做用域僅侷限於本文件(因此又稱內部函數)。使用內部函數的好處是:不一樣的人編寫不一樣的函數時,不用擔憂本身定義的函數,是否會與其它文件中的函數同名。

擴展分析:

      術語static有着不尋常的歷史.起初,在C中引入關鍵字static是爲了表示退出一個塊後仍然存在的局部變量。隨後,staticC中有了第二種含義:用來表示不能被其它文件訪問的全局變量和函數。爲了不引入新的關鍵字,因此仍使用static關鍵字來表示這第二種含義。最後,C++重用了這個關鍵字,並賦予它與前面不一樣的第三種含義:表示屬於一個類而不是屬於此類的任何特定對象的變量和函數(Java中此關鍵字的含義相同)

全局變量、靜態全局變量、靜態局部變量和局部變量的區別

變量能夠分爲:全局變量、靜態全局變量、靜態局部變量和局部變量。


         

存儲區域分,全局變量、靜態全局變量和靜態局部變量都存放在內存的靜態存儲區域,局部變量存放在內存的棧區
         
做用域分,  全局變量在整個工程文件內都有效;靜態全局變量只在定義它的文件內有效;靜態局部變量只在定義它的函數內有效,只是程序僅分配一次內存,函數返回後,該變量不會消失;局部變量在定義它的函數內有效,可是函數返回後失效

    全局變量(外部變量)的說明以前再冠以static 就構成了靜態的全局變量。全局變量自己就是靜態存儲方式, 靜態全局變量固然也是靜態存儲方式。 這二者在存儲方式上並沒有不一樣。這二者的區別雖在於非靜態全局變量的做用域是整個源程序, 當一個源程序由多個源文件組成時,非靜態的全局變量在各個源文件中都是有效的。 而靜態全局變量則限制了其做用域, 即只在定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。因爲靜態全局變量的做用域侷限於一個源文件內,只能爲該源文件內的函數公用, 所以能夠避免在其它源文件中引發錯誤。

從以上分析能夠看出, 把局部變量改變爲靜態變量後是改變了它的存儲方式即改變了它的生存期。把全局變量改變爲靜態變量後是改變了它的做用域 限制了它的使用範圍。

static 函數與普通函數做用域不一樣。僅在本文件。只在當前源文件中使用的函數應該說明爲內部函數(static),內部函數應該在當前源文件中說明和定義。對於可在當前源文件之外使用的函數,應該在一個頭文件中說明,要使用這些函數的源文件要包含這個頭文件

static全局變量與普通的全局變量有什麼區別:static全局變量只初始化一次,防止在其餘文件單元中被引用;
static局部變量和普通局部變量有什麼區別:static局部變量只被初始化一次,下一次依據上一次結果值;

    static
函數與普通函數有什麼區別:static函數在內存中只有一份,普通函數在每一個被調用中維持一份拷貝
    
全局變量和靜態變量若是沒有手工初始化,則由編譯器初始化爲0。局部變量的值不可知。

——————————————————————————————————————

 C++static有兩種用法:面向過程程序設計中的static和麪向對象程序設計中的static。前者應用於普通變量和函數,不涉及類;後者主要說明static在類中的做用。

1、面向過程設計中的static

1、靜態全局變量

在全局變量前,加上關鍵字static,該變量就被定義成爲一個靜態全局變量。咱們先舉一個靜態全局變量的例子,以下: 

//Example 1

#include <iostream.h>

void fn();

static int n; //定義靜態全局變量

void main()

{

 n=20;

 cout<<n<<endl;

 fn();

}

void fn()

{

 n++;

 cout<<n<<endl;

}

靜態全局變量有如下特色:  

·                                

該變量在全局數據區分配內存;  

·                                

 未經初始化的靜態全局變量會被程序自動初始化爲0(自動變量的值是隨機的,除非它被顯式初始化);  

·                                

 靜態全局變量在聲明它的整個文件都是可見的,而在文件以外是不可見的;   

靜態變量都在全局數據區分配內存,包括後面將要提到的靜態局部變量。對於一個完整的程序,在內存中的分佈狀況以下圖:
   

代碼區

全局數據區

堆區

棧區

  通常程序的由new產生的動態數據存放在堆區,函數內部的自動變量存放在棧區。自動變量通常會隨着函數的退出而釋放空間,靜態數據(即便是函數內部的靜態局部變量)也存放在全局數據區。全局數據區的數據並不會由於函數的退出而釋放空間。細心的讀者可能會發現,Example 1中的代碼中將 

 static int n; //定義靜態全局變量

改成 

 int n; //定義全局變量

相關文章
相關標籤/搜索