[ASM/C/C++]c語言中static 用法總結

來源:互聯網
上載者:User

假設在test.h中定義了一個static bool g_test=false;

若test1.c和test2.c都包含test.h,則test1.c和test2.c分別產生兩份g_test,在test1.c 中置g_test=true,而test2.c中仍然為false並未改變!shit!!

一、c程式儲存空間布局

C程式一直由下列部分組成:

      1)本文段——CPU執行的機器指令部分;一個程式只有一個副本;唯讀,防止程式由於意外事故而修改自身指令;
      2)初始化資料區段(資料區段)——在程式中所有賦了初值的全域
變數
,存放在這裡。
      3)非初始化資料區段(bss段)——在程式中沒有初始化的全域變數
;核心將此段初始化為0。
      4)棧——增長方向:自頂向下增長;自動變數
以及每次函數調用時所需要儲存的資訊(返回地址;環境資訊)。
      5)堆——動態儲存裝置分。

|-----------|
|                 |
|-----------|
|    棧         | 
|-----------|
|    |            |
|   |/           |
|                 |
|                 |
|   /|           |
|    |            |
|-----------|
|    堆         |
|-----------|
| 未初始化  |
|-----------|
|   初始化  |
|-----------|
|  本文段   |
|-----------|

二、 面向過程程式設計中的static

1. 全域靜態變數

   在全域變數
之前加上關鍵字static
,全域變數
就被定義成為一個全域靜態變數

   1)記憶體中的位置:靜態儲存區(靜態儲存區在整個程式運行期間都存在)

   2)初始化:未經初始化的全域靜態變數
會被程式自動初始化為0(自動對象的值是任意的,除非他被顯示初始化)

   3)範圍:全域靜態變數
在聲明他的
檔案
之外是不可見的。準確地講從定義之處開始到檔案
結尾。

看下面關於範圍的程式:
//teststatic1.c
void display();
extern int n;
int main()
{
  n = 20;
  printf("%dn",n);
  display();
  return 0;
}
 
//teststatic2.c 
static
int n;   //定義全域靜態變數
,自動初始化為0,僅在本檔案
中可見
void display()
{
  n++;
  printf("%dn",n);
}

檔案
分別編譯通過,但link的時候teststatic2.c
中的變數
n找不到定義,產生錯誤。
 
定義全域靜態變數
的好處:

<1>不會被其他檔案
所訪問,修改

<2>其他檔案
中可以使用相同名字的變數
,不會發生衝突。

2. 局部靜態變數

  在局部變數
之前加上關鍵字static
,局部變數
就被定義成為一個局部靜態變數

  1)記憶體中的位置:靜態儲存區

  2)初始化:未經初始化的全域靜態變數
會被程式自動初始化為0(自動對象的值是任意的,除非他被顯示初始化)

  3)範圍:範圍仍為局部範圍,當定義它的函數或者語句塊結束的時候,範圍隨之結束。

  註:當static
用來修飾局部變數
的時候,它就改變了局部變數
的儲存位置,從原來的棧中存放改為靜
態儲存區。但是局部靜態變數
在離開範圍之後,並沒有被銷毀,而是仍然駐留在記憶體當中,直到程式結束,只不過我們不能再對他進行訪問。

      當static
用來修飾全域變數
的時候,它就改變了全域變數
的範圍(在聲明他的檔案
之外是不可見的),但是沒有改變它的存放位置,還是在靜態儲存區中。

3. 靜態函數

  在函數的傳回型別前加上關鍵字static
,函數就被定義成為靜態函數。

  函數的定義和聲明預設情況下是extern的,但靜態函數只是在聲明他的檔案
當中可見,不能被其他檔案
所用。

  例如:
//teststatic1.c
void display();
static
void staticdis();
int main()
{
  display();
  staticdis();
  renturn 0;
}
 
//teststatic2.c
void display()
{
  staticdis();
  printf("display() has been called n");
}
 
static
void staticdis()
{
  printf("staticDis() has been calledn");
}
 
檔案
分別編譯通過,但是串連的時候找不到函數staticdis()的定義,產生錯誤。
 實際上編譯也未過,vc2003報告teststatic1.c中靜態函數staticdis已聲明但未定義 ;by imjacob

定義靜態函數的好處:

<1> 其他檔案
中可以定義相同名字的函數,不會發生衝突

<2> 靜態函數不能被其他檔案
所用。
 
儲存說明符auto,register,extern,static
,對應兩種儲存期:自動儲存期和靜態儲存期。
 
auto和register對應自動儲存期。具有自動儲存期的變數
在進入聲明該變數
的程式塊時被建立,它在該程式塊活動時存在,退出該程式塊時撤銷。

關鍵字extern和static
用來說明具有靜態儲存期的變數
和函數。用static
聲明的局部變數
具有靜態儲存持續期(static
storage duration),或靜態範圍(static
extent)。雖然他的值在函數調用之間保持有效,但是其名字的可視性仍限制在其局部域內。靜態局部對象在程式執行到該對象的聲明處時被首次初始化。

由於static
變數
的以上特性,可實現一些特定功能。

1. 統計次數功能

聲明函數的一個局部變數
,並設為static
類型,作為一個計數器,這樣函數每次被調用的時候就可以進行計數。這是統計函數被調用次數的最好的辦法,因為這個變數
是和函數息息相關的,而函數可能在多個不同的地方被調用,所以從調用者的角度來統計比較困難。代碼如下:
 
void count();
int main()
{
 int i;
 for (i = 1; i <= 3; i++)
  count();
  return 0;
}
void count()
{
 static
num = 0;
 num++;
 printf(" I have been called %d",num,"timesn");
}

輸出結果為:
I have been called 1 times.
I have been called 2 times.
I have been called 3 times.

 

轉自:http://dream2fly.net/blog/?action=show&id=75

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.