• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            春暖花開(kāi)
            雪化了,花開(kāi)了,春天來(lái)了
            posts - 149,comments - 125,trackbacks - 0

            今日從網(wǎng)上看到一篇好文章,匯總匯總,又拼湊拼湊,便有了下文。
             

            static關(guān)鍵字是C、C++中都存在的關(guān)鍵字, 它主要有三種使用方式, 其中前兩種只指在C語(yǔ)言中使用, 第三種在C++中使用(C,C++中具體細(xì)微操作不盡相同,   本文以C++為準(zhǔn)).  

            (1) 局部靜態(tài)變量 靜態(tài)局部變量有兩個(gè)用法,記憶功能和全局生存期.

            (2) 外部靜態(tài)變量/函數(shù) 用于全局變量,主要作用是限制此全局變量被其他的文件調(diào)用

            (3) 靜態(tài)數(shù)據(jù)成員/成員函數(shù) 表示這個(gè)成員是屬于這個(gè)類但是不屬于類中任意特定對(duì)象

             

            下面就這三種使用方式及注意事項(xiàng)分別說(shuō)明

             一、局部靜態(tài)變量  
             
            C/C++, 局部變量按照存儲(chǔ)形式可分為三種auto, static, register  

             auto類型(普通)局部變量相比, static局部變量有三點(diǎn)不同

              1.   存儲(chǔ)空間分配不同 

              auto類型分配在棧上, 屬于動(dòng)態(tài)存儲(chǔ)類別, 占動(dòng)態(tài)存儲(chǔ)區(qū)空間, 函數(shù)調(diào)用結(jié)束后自動(dòng)釋放, static分配在靜態(tài)存儲(chǔ)區(qū), 在程序整個(gè)運(yùn)行期間都不釋放. 兩者之間的作用域相同, 但生存期不同.  

              2.   static局部變量在所處模塊在初次運(yùn)行時(shí)進(jìn)行初始化工作, 且只操作一次 

              3.   對(duì)于局部靜態(tài)變量, 如果不賦初值, 編譯期會(huì)自動(dòng)賦初值0或空字符, auto類型的初值是不確定的.(對(duì)于C++中的class對(duì)象例外, class的對(duì)象實(shí)例如果不初始化, 則會(huì)自動(dòng)調(diào)用默認(rèn)構(gòu)造函數(shù), 不管是否是static類型)  

             特點(diǎn): static局部變量的記憶性與生存期的全局性”  

             所謂“記憶性是指在兩次函數(shù)調(diào)用時(shí), 在第二次調(diào)用進(jìn)入時(shí), 能保持第一次調(diào)用退出時(shí)的值.    

             示例程序一 

              #include   <iostream>  

              using   namespace   std;  

              void   staticLocalVar()  

              {  

            static  int a  = 0; // 運(yùn)行期時(shí)初始化一次,下次再調(diào)用時(shí),不進(jìn)行初始化工作 

            cout<<"a="<<a<<endl;  

            ++a;  

            }  

            int   main()  

            {  

                staticLocalVar();   //  第一次調(diào)用,   輸出a=0  

                staticLocalVar();   // 第二次調(diào)用,   記憶了第一次退出時(shí)的值,   輸出a=1  

                return   0;  

            }  

             應(yīng)用:  利用“記憶性”,   記錄函數(shù)調(diào)用的次數(shù)(示例程序一)

                   

            利用生存期的“全局性,改善

            return a   pointer   /   reference   to   a   local   object”的問(wèn)題. Local object的問(wèn)題在于退出函數(shù), 生存期即結(jié)束,利用static的作用, 延長(zhǎng)變量的生存期.  

             示例程序二:  

              //   IP   address   to   string   format  

              //   Used   in   Ethernet   Frame   and   IP   Header   analysis  

              const   char   *   IpToStr(UINT32   IpAddr)  

              {  

                static   char   strBuff[16];   //   static局部變量,   用于返回地址有效

                const  unsigned   char  *pChIP   =  (const   unsigned   char   *)&IpAddr;

               sprintf(strBuff, "%u.%u.%u.%u", pChIP[0], pChIP[1],  pChIP[2], pChIP[3]);  

                return   strBuff;  

              }  

             注意事項(xiàng):  

              1. “記憶性”,  程序運(yùn)行很重要的一點(diǎn)就是可重復(fù)性, static變量的記憶性破壞了這種可重復(fù)性,   造成不同時(shí)刻至運(yùn)行的結(jié)果可能不同.  

              2.  “生存期全局性和唯一性. 普通的local變量的存儲(chǔ)空間分配在stack,  因此每次調(diào)用函數(shù)時(shí),  分配的空間都可能不一樣, static具有全局唯一性的特點(diǎn), 每次調(diào)用時(shí), 都指向同一塊內(nèi)存, 這就造成一個(gè)很重要的問(wèn)題   ----   不可重入性!!!  

             

             這樣在多線程程序設(shè)計(jì)或遞歸程序設(shè)計(jì)中,  要特別注意這個(gè)問(wèn)題.

             下面針對(duì)示例程序二,   分析在多線程情況下的不安全性.(為方便描述,   標(biāo)上行號(hào)

            const   char   *   IpToStr(UINT32   IpAddr)  

              {  

              static   char   strBuff[16];   //   static局部變量,   用于返回地址有效

                const  unsigned   char  *pChIP   =  (const   unsigned   char   *)&IpAddr;

               sprintf(strBuff, "%u.%u.%u.%u", pChIP[0], pChIP[1],  pChIP[2], pChIP[3]);  

                return   strBuff;  

              }  

             

               假設(shè)現(xiàn)在有兩個(gè)線程A,B運(yùn)行期間都需要調(diào)用IpToStr()函數(shù), 32位的IP地址轉(zhuǎn)換成點(diǎn)分10進(jìn)制的字符串形式.  

            現(xiàn)A先獲得執(zhí)行機(jī)會(huì), 執(zhí)行IpToStr(), 傳入的參數(shù)是0x0B090A0A, 順序執(zhí)行完應(yīng)該返回的指針存儲(chǔ)區(qū)內(nèi)容是: “10.10.9.11”, 現(xiàn)執(zhí)行到⑥時(shí), 失去執(zhí)行權(quán), 調(diào)度到B線程執(zhí)行, B線程傳入的參數(shù)是0xA8A8A8C0,執(zhí)行至⑦, 靜態(tài)存儲(chǔ)區(qū)的內(nèi)容是192.168.168.168. 當(dāng)再調(diào)度到A執(zhí)行時(shí), 從⑥繼續(xù)執(zhí)行, 由于strBuff的全局唯一性, 內(nèi)容已經(jīng)被B線程沖掉, 此時(shí)返回的將是192.168.168.168字符串, 不再是10.10.9.11字符串.  

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

            (2)允許對(duì)構(gòu)造類靜態(tài)局部量賦初值    例如數(shù)組,若未賦以初值,則由系統(tǒng)自動(dòng)賦以0值。
            (3)
            對(duì)基本類型的靜態(tài)局部變量若在說(shuō)明時(shí)未賦以初值,則系統(tǒng)自動(dòng)賦予0值。而對(duì)自動(dòng)變量不賦初值,則其值是不定的。根據(jù)靜態(tài)局部變量的特點(diǎn), 可以看出它是一種生存期為整個(gè)源程序的量。雖然離開(kāi)定義它的函數(shù)后不能使用,但如再次調(diào)用定義它的函數(shù)時(shí),它又可繼續(xù)使用, 而且保存了前次被調(diào)用后留下的值。因此,當(dāng)多次調(diào)用一個(gè)函數(shù)且要求在調(diào)用之間保留某些變量的值時(shí),可考慮采用靜態(tài)局部變量。雖然用全局變量也可以達(dá)到上述目的,但全局變量有時(shí)會(huì)造成意外的副作用,因此仍以采用局部靜態(tài)變量為宜

             

              二、外部靜態(tài)變量/函數(shù) 

               Cstatic有了第二種含義:用來(lái)表示不能被其它文件訪問(wèn)的全局變量和函數(shù)。 但為了限制全局變量/函數(shù)的作用域,  函數(shù)或變量前加static使得函數(shù)成為靜態(tài)函數(shù)。但此處“static”的含義不是指存儲(chǔ)方式,而是指對(duì)函數(shù)的作用域僅局限于本文件(所以又稱內(nèi)部函數(shù))。注意此時(shí), 對(duì)于外部(全局)變量, 不論是否有static限制, 它的存儲(chǔ)區(qū)域都是在靜態(tài)存儲(chǔ)區(qū), 生存期都是全局的. 此時(shí)的static只是起作用域限制作用, 限定作用域在本模塊(文件)內(nèi)部.  

             使用內(nèi)部函數(shù)的好處是:不同的人編寫(xiě)不同的函數(shù)時(shí),不用擔(dān)心自己定義的函數(shù),是否會(huì)與其它文件中的函數(shù)同名。

             示例程序三:  

              //file1.cpp  

              static   int   varA;  

              int   varB;  

              extern   void   funA()  

              {  

              ……  

              }  

              static   void   funB()  

              {  

              ……  

              }

             

              //file2.cpp  

              extern   int   varB;   //   使用file1.cpp中定義的全局變量 

              extern   int   varA;   //   錯(cuò)誤! varAstatic類型,  無(wú)法在其他文件中使用 

              extern   vod   funA(); //   使用file1.cpp中定義的函數(shù) 

              extern   void   funB(); //   錯(cuò)誤! 無(wú)法使用file1.cpp文件中static函數(shù) 

             

            補(bǔ)充:全局變量(外部變量)的說(shuō)明之前再冠以static 就構(gòu)成了靜態(tài)的全局變量。全局變量本身就是靜態(tài)存儲(chǔ)方式, 靜態(tài)全局變量當(dāng)然也是靜態(tài)存儲(chǔ)方式。 這兩者在存儲(chǔ)方式上并無(wú)不同。這兩者的區(qū)別雖在于非靜態(tài)全局變量的作用域是整個(gè)源程序,當(dāng)一個(gè)源程序由多個(gè)源文件組成時(shí),非靜態(tài)的全局變量在各個(gè)源文件中都是有效的。 而靜態(tài)全局變量則限制了其作用域, 即只在定義該變量的源文件內(nèi)有效, 在同一源程序的其它源文件中不能使用它。由于靜態(tài)全局變量的作用域局限于一個(gè)源文件內(nèi),只能為該源文件內(nèi)的函數(shù)公用,因此可以避免在其它源文件中引起錯(cuò)誤。從以上分析可以看出, 把局部變量改變?yōu)殪o態(tài)變量后是改變了它的存儲(chǔ)方式即改變了它的生存期。把全局變量改變?yōu)殪o態(tài)變量后是改變了它的作用域,限制了它的使用范圍。因此static 這個(gè)說(shuō)明符在不同的地方所起的作用是不同的。

             

              三、靜態(tài)數(shù)據(jù)成員/成員函數(shù)(C++特有)  

              C++重用了這個(gè)關(guān)鍵字,并賦予它與前面不同的第三種含義:表示屬于一個(gè)類而不是屬于此類的任何特定對(duì)象的變量和函數(shù). 這是與普通成員函數(shù)的最大區(qū)別, 也是其應(yīng)用所在, 比如在對(duì)某一個(gè)類的對(duì)象進(jìn)行計(jì)數(shù)時(shí),計(jì)數(shù)生成多少個(gè)類的實(shí)例, 就可以用到靜態(tài)數(shù)據(jù)成員. 在這里面, static既不是限定作用域的, 也不是擴(kuò)展生存期的作用, 指示變量/函數(shù)在此類中的唯一性. 這也是屬于一個(gè)類而不是屬于此類的任何特定對(duì)象的變量和函數(shù)的含義.  因?yàn)樗菍?duì)整個(gè)類來(lái)說(shuō)是唯一的, 因此不可能屬于某一個(gè)實(shí)例對(duì)象的. (針對(duì)靜態(tài)數(shù)據(jù)成員而言, 成員函數(shù)不管是否是static,在內(nèi)存中只有一個(gè)副本.普通成員函數(shù)調(diào)用時(shí), 需要傳入this指針,static成員函數(shù)調(diào)用時(shí), 沒(méi)有this指針.   )  

             請(qǐng)看示例程序四

              class   EnemyTarget   {  

              public:  

                  EnemyTarget()   {   ++numTargets;   }  

                  EnemyTarget(const   EnemyTarget&)   {   ++numTargets;   }  

                  ~EnemyTarget()   {   --numTargets;   }  
                  static   size_t   numberOfTargets()   {   return   numTargets;   }  

                  bool  destroy(); //   returns  success  of  attempt  to  destroy  

            // EnemyTarget   object  

                  private:  

                  static   size_t   numTargets;   //   object   counter  

              };  

              //   class   statics   must   be   defined   outside   the   class;  

              //   initialization   is   to   0   by   default  

              size_t   EnemyTarget::numTargets;  

             在這個(gè)例子中,   靜態(tài)數(shù)據(jù)成員numTargets就是用來(lái)計(jì)數(shù)產(chǎn)生的對(duì)象個(gè)數(shù)的.  

            在《c++ 程序設(shè)計(jì)語(yǔ)言》中,是這樣運(yùn)用的:
             

            Static靜態(tài)成員,它是類的一部分,但卻不是該類的各個(gè)對(duì)象的一部分。一個(gè)static成員只有唯一的一份副本,但不像常規(guī)的非static成員那樣在每個(gè)對(duì)象里各有一份副本。 與此類似,一個(gè)需要訪問(wèn)類成員,然而卻并不需要針對(duì)特定對(duì)象去調(diào)用的函數(shù),也被稱為一個(gè)static成員函數(shù)。其好處在于消除了由于依賴全局量而引起的問(wèn)題

            Class Date

            {

               Int d, m, y;

               Static Date default_date;

               Public:

                  Date(int dd=0, int mm=0, int yy=0);

                  //……

                  Static void set_default(int, int, int);

            };

            靜態(tài)成員可以像任何其他成員一樣引用,此外,對(duì)于靜態(tài)成員的引用不必提到任何對(duì)象,相反,在這里應(yīng)該成員的名字加上作為限定詞的類的名字。

            Void f()

            {

             Date::set_default(4, 5, 1945);

            }

            靜態(tài)成員(包括函數(shù)和數(shù)據(jù)成員)都必須在某個(gè)地方另行定義。如

            Date Date:::default_date(16, 12, 1770);

            Void Date::set_default(int d, int m, int y)

            {

             Date::default_date = Date(d, m, y);

            }

             

            補(bǔ)充:內(nèi)部函數(shù)和外部函數(shù)

            當(dāng)一個(gè)源程序由多個(gè)源文件組成時(shí),C語(yǔ)言根據(jù)函數(shù)能否被其它源文件中的函數(shù)調(diào)用,將函數(shù)分為內(nèi)部函數(shù)和外部函數(shù)。
            1
            內(nèi)部函數(shù)(又稱靜態(tài)函數(shù))
            如果在一個(gè)源文件中定義的函數(shù),只能被本文件中的函數(shù)調(diào)用,而不能被同一程序其它文件中的函數(shù)調(diào)用,這種函數(shù)稱為內(nèi)部函數(shù)。
            定義一個(gè)內(nèi)部函數(shù),只需在函數(shù)類型前再加一個(gè)“static”關(guān)鍵字即可,如下所示:
            static   
            函數(shù)類型    函數(shù)名(函數(shù)參數(shù)表)
            {……}
            關(guān)鍵字“static”,譯成中文就是靜態(tài)的,所以內(nèi)部函數(shù)又稱靜態(tài)函數(shù)。但此處“static”的含義不是指存儲(chǔ)方式,而是指對(duì)函數(shù)的作用域僅局限于本文件。
            使用內(nèi)部函數(shù)的好處是:不同的人編寫(xiě)不同的函數(shù)時(shí),不用擔(dān)心自己定義的函數(shù),是否會(huì)與其它文件中的函數(shù)同名,因?yàn)橥矝](méi)有關(guān)系。

            2 外部函數(shù)
            外部函數(shù)的定義:在定義函數(shù)時(shí),如果沒(méi)有加關(guān)鍵字“static”,或冠以關(guān)鍵字“extern”,表示此函數(shù)是外部函數(shù):
            [extern]   
            函數(shù)類型    函數(shù)名(函數(shù)參數(shù)表)
            {……}
            調(diào)用外部函數(shù)時(shí),需要對(duì)其進(jìn)行說(shuō)明:
            [extern]   
            函數(shù)類型    函數(shù)名(參數(shù)類型表)[,函數(shù)名2(參數(shù)類型表2)……];

             

            posted on 2008-10-11 10:40 Sandy 閱讀(398) 評(píng)論(1)  編輯 收藏 引用

            FeedBack:
            # re: static 用法總結(jié)
            2008-10-11 10:45 | gggggggggggggg

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            狠狠久久综合伊人不卡| 婷婷久久综合| 国产亚洲成人久久| 狠狠色丁香久久婷婷综合图片| 国产69精品久久久久APP下载| av色综合久久天堂av色综合在| 国产精品久久久久9999高清| 少妇被又大又粗又爽毛片久久黑人| 亚洲天堂久久久| 久久精品免费大片国产大片| 久久99精品国产麻豆| 人妻无码久久精品| 精品人妻伦一二三区久久| 久久人妻少妇嫩草AV无码专区| 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 色综合合久久天天综合绕视看 | 色综合久久久久综合体桃花网| 国内精品久久久久久久coent| 久久婷婷五月综合97色一本一本| 久久人人爽人爽人人爽av | 久久97精品久久久久久久不卡| 久久精品国产2020| 亚洲精品无码久久不卡| 精品一久久香蕉国产线看播放| 国产成人无码久久久精品一| 久久久亚洲AV波多野结衣| 波多野结衣久久一区二区| 无码人妻久久一区二区三区蜜桃| 亚洲一区二区三区日本久久九| 午夜精品久久久久久99热| 午夜久久久久久禁播电影| 亚洲AV无码久久精品成人| 久久久久亚洲AV无码观看| 亚洲国产视频久久| 日本五月天婷久久网站| 伊人久久亚洲综合影院| 久久久久国产精品人妻| 久久偷看各类wc女厕嘘嘘| 久久久女人与动物群交毛片| avtt天堂网久久精品| 9191精品国产免费久久|