找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 8103|回復: 2
打印 上一主題 下一主題
收起左側

static C語言 靜態(tài)變量和靜態(tài)函數(shù)

[復制鏈接]
跳轉到指定樓層
樓主
ID:98924 發(fā)表于 2015-12-9 02:42 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

問題雖然是C語言中的靜態(tài)變量,其實說起來在其他很多的編程語言中,靜態(tài)變量的意義和用法都和C語言中差不多,所以搞懂了這個概念在以后學習其他的編程語言的時候是很有作用的。


我們就來說說C語言中的靜態(tài)變量是什么樣的一種,靜態(tài)變量在它們自己的函數(shù)或者是文件中是永久的變量,說起來,靜態(tài)變量很像是全局變量,但是他們之間是有差別的,靜態(tài)變量在函數(shù)或者是文件中是不被知道的,他們在兩次調用之間將保存自己的值,比如說,假如一個靜態(tài)變量的值是1,在第一次調用靜態(tài)變量之后,將他的值變?yōu)?,那么在我們第二次調用它的時候,它的值依然是2,而不會去初始化它,將它的值又看作是1。
Ex:

c語言 static靜態(tài)變量

#include iostream.h 
int p(int x)
{
static int y=1;
y=y+1;
return (x+y);}
int main()
{
cout<<p(1)<<endl;
cout<<p(2)<<endl;}

答案是3和5,為什么不是3和4呢?

c語言的static變量是在程序加載的時候就為之分配內存的,一直到程序結束,而不像普通變量那樣函數(shù)執(zhí)行一次分配一次。所以當?shù)谝淮螆?zhí)行p(1)的時候,y已經(jīng)加1了,下次執(zhí)行p(2)時,y不會恢復成1,還是2;你就當全局變量的功能處理就行,性能上有區(qū)別

-----------------------------------------------------------------------------------------------------------------------
以下是基礎知識點
-----------------------------------------------------------------------------------------------------------------------

1. static 變量

靜態(tài)變量的類型 說明符是static。 靜態(tài)變量當然是屬于靜態(tài)存儲方式,但是屬于靜態(tài)存儲方式的量不一定就是靜態(tài)變量。 例如外部變量雖屬于靜態(tài) 存儲方式,但不一定是靜態(tài)變量,必須由 static加以定義后才能成為靜態(tài)外部變量,或稱靜態(tài)全局變量。

2. 靜態(tài)局部變量

靜態(tài)局部變量屬于靜態(tài)存儲方式,它具有以下特點:
(1)靜態(tài)局部變量在函數(shù)內定義 它的生存期為整個源程序,但是其作用域仍與自動變量相同,只能在定義該變量的函數(shù)內使用該變量。退出該函數(shù)后, 盡管該變量還繼續(xù)存在,但不能使用它。

(2)允許對構造類靜態(tài)局部量賦初值 例如數(shù)組,若未賦以初值,則由系統(tǒng)自動賦以0值。

(3) 對基本類型的靜態(tài)局部變量若在說明時未賦以初值,則系統(tǒng)自動賦予0值。而對自動變量不賦初值,則其值是不定的。
 

根據(jù)靜態(tài)局部變量的特點,可以看出它是一種生存期為整個源程序的量。雖然離開定義它的函數(shù)后不能使用,但如果再次調用定義它的函數(shù)時,它又可繼續(xù)使用, 而且保存了前次被調用后留下的值。因此,當多次調用一個函數(shù)且要求在調用之間保留某些變量的值時,可考慮采用靜態(tài)局部變量。雖然用全局變量也可以達到上述目的,但全局變量有時會造成意外的副作用,因此仍以采用局部靜態(tài)變量為宜。

3.靜態(tài)全局變量
全局變量(外部變量)的說明之前再冠以static 就構成了靜態(tài)的全局變量。全局變量本身就是靜態(tài)存儲方式, 靜態(tài)全局變量當然也是靜態(tài)存儲方式。這兩者在存儲方式上并無不同。這兩者的區(qū)別雖在于非靜態(tài)全局變量的作用域是整個源程序,當一個源程序由多個源文件組成時,非靜態(tài)的全局變量在各個源文件中都是有效的。 而靜態(tài)全局變量則限制了其作用域, 即只在定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。由于靜態(tài)全局變量的作用域局限于一個源文件內,只能為該源文件內的函數(shù)公用,因此 可以避免在其它源文件中引起錯誤。

從以上分析可以看出:
把局部變量改變?yōu)殪o態(tài)變量后是改變了它的存儲方式即改變了它的生存期
把全局變量改變?yōu)殪o態(tài)變量 后是改變了它的作用域,限制了它的使用范圍

因此static 這個說明符在不同的地方所起的作用是不同的。

4. static 函數(shù)…..

內部函數(shù)和外部函數(shù)

當一個源程序由多個源文件組成時,C語言根據(jù)函數(shù)能否被其它源文件中的函數(shù)調用,將函數(shù)分為內部函數(shù)和外部函數(shù)。

1 內部函數(shù)(又稱靜態(tài)函數(shù))
如果在一個源文件中定義的函數(shù),只能被本文件中的函數(shù)調用,而不能被同一程序其它文件中的函數(shù)調用,這種函數(shù)稱為內部函數(shù)。
定義一個內部函數(shù),只需在函數(shù)類型前再加一個“static”關鍵字即可,如下所示:
static 函數(shù)類型 函數(shù)名(函數(shù)參數(shù)表)
{……}
關鍵字“static”,譯成中文就是“靜態(tài)的”,所以內部函數(shù)又稱靜態(tài)函數(shù)。但此處“static”的含義不是指存儲方式,而是指對函數(shù)的作用域僅局限于本文件。
使用內部函數(shù)的好處是:不同的人編寫不同的函數(shù)時,不用擔心自己定義的函數(shù),是否會與其它文件中的函數(shù)同名,因為同名也沒有關系。

2 外部函數(shù)

外部函數(shù)的定義:在定義函數(shù)時,如果沒有加關鍵字“static”,或冠以關鍵字“extern”,表示此函數(shù)是外部函數(shù):
[extern] 函數(shù)類型 函數(shù)名(函數(shù)參數(shù)表)
{……}
調用外部函數(shù)時,需要對其進行說明
[extern] 函數(shù)類型 函數(shù)名(參數(shù)類型表)[,函數(shù)名2(參數(shù)類型表2)……];

[案例]外部函數(shù)應用。

(1)文件mainf.c
main()
{ extern void input(…),process(…),output(…); /*調用外部函數(shù)*/
input(…); process(…); output(…);
}

(2)文件subf1.c
……
extern void input(……) /*定義外部函數(shù)*/
{……}
(3)文件subf2.c
……
extern void process(……) /*定義外部 函數(shù)*/
{……}
(4)文件subf3.c
……
extern void output(……) /*定義外部函數(shù)*/
{……}


注:此處的extern可有可無,不加extern時默認是外部函數(shù)

------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------

1、概述

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

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


2、問題:Static的理解


  關于static變量,請選擇下面所有說法正確的內容:

  A、若全局變量僅在單個C文件中訪問,則可以將這個變量修改為靜態(tài)全局變量,以降低模塊間的耦合度;

  B、若全局變量僅由單個函數(shù)訪問,則可以將這個變量改為該函數(shù)的靜態(tài)局部變量,以降低模塊間的耦合度;

  C、設計和使用訪問動態(tài)全局變量、靜態(tài)全局變量、靜態(tài)局部變量的函數(shù)時,需要考慮重入問題;

  D、靜態(tài)全局變量過大,可那會導致堆棧溢出。 

  答案與分析:

  對于A,B:根據(jù)本篇概述部分的說明b),我們知道,A,B都是正確的。

  對于C:根據(jù)本篇概述部分的說明a),我們知道,C是正確的(所謂的函數(shù)重入問題,下面會詳細闡述)。

  對于D:靜態(tài)變量放在程序的全局數(shù)據(jù)區(qū),而不是在堆棧中分配,所以不可能導致堆棧溢出,D是錯誤的。

  因此,答案是A、B、C。

  3、問題:不可重入函數(shù)

  曾經(jīng)設計過如下一個函數(shù),在代碼檢視的時候被提醒有bug,因為這個函數(shù)是不可重入的,為什么?

unsigned int sum_int( unsigned int base )
{
 unsigned int index;
 static unsigned int sum = 0; // 注意,是static類型的。 
 for (index = 1; index <= base; index++)
 {
  sum += index;
 }
 return sum;
}

  答案與分析:

  所謂的函數(shù)是可重入的(也可以說是可預測的),即:只要輸入數(shù)據(jù)相同就應產生相同的輸出。

   這個函數(shù)之所以是不可預測的,就是因為函數(shù)中使用了static變量,因為static變量的特征,這樣的函數(shù)被稱為:帶“內部存儲器”功能的的函數(shù)。 因此如果我們需要一個可重入的函數(shù),那么,我們一定要避免函數(shù)中使用static變量,這種函數(shù)中的static變量,使用原則是,能不用盡量不用。

  將上面的函數(shù)修改為可重入的函數(shù)很簡單,只要將聲明sum變量中的static關鍵字去掉,變量sum即變?yōu)橐粋auto 類型的變量,函數(shù)即變?yōu)橐粋可重入的函數(shù)。

  當然,有些時候,在函數(shù)中是必須要使用static變量的,比如當某函數(shù)的返回值為指針類型時,則必須是static的局部變量的地址作為返回值,若為auto類型,則返回為錯指針。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發(fā)
ID:99580 發(fā)表于 2015-12-19 20:56 | 只看該作者
好,謝謝樓主分享。
回復

使用道具 舉報

板凳
ID:296746 發(fā)表于 2018-3-26 17:07 | 只看該作者
牛人!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表