C/C++?extern和static的使用詳解
前言
在講到extern和static的時(shí)候先了解一下定義和聲明的基本概念
定義(define):
A variable is defined when the compiler allocates the storage for the variable,就是我們的變量個(gè)其存儲(chǔ)的具體值相關(guān)聯(lián)
聲明(declared)
編譯器聲明這個(gè)變量的存在,宣告其類(lèi)型但是并不關(guān)聯(lián)某個(gè)存儲(chǔ)的具體值
你可以聲明一個(gè)變量多次,但是你只能定義其一次并且給一個(gè)范圍,我們定義一個(gè)變量也是聲明,但不是所有的聲明都是定義
extern
我們?cè)谌致暶?定義一個(gè)變量最好的一個(gè)方法是在頭文件中用關(guān)鍵字extern
聲明一個(gè)變量
在我們工程中,一般用一個(gè)頭文件聲明全部所需的全局變量(當(dāng)然用extern
),然后在所有其他的.c文件中include這個(gè)頭文件,假設(shè)我們有三個(gè)文件分別是file3.h
,file1.c
,file2.c
內(nèi)容分別如下var.h
extern int global_var;
var.c
#include "var.h" #include "prog1.h" //function declarations,我們示例中沒(méi)有將函數(shù)原型頭文件寫(xiě)出來(lái) int global_var = 33; int increment(void) { return global_variable++ }
main.c
#include "var.h" #include "prog1.h" #include <stdio.h> //注意我們沒(méi)有include file1.c void use_it(void){ printf("global var : %d\n",global_var++); }
然后我們編譯 (記住不編譯頭文件)
gcc main.c var.c -o out.c
為什么我們的main不include var.c就知道global_var的具體值呢?因?yàn)槲覀冋f(shuō)過(guò)一個(gè)全局變量只能定義一次,但是可以聲明多次,global_var分別在main,c和var.c中聲明了,但是只在var.c中定義,換個(gè)角度,global_var的生命周期是全局也就是整個(gè)軟件的生命周期,整個(gè)軟件的生命周期包含三個(gè)文件,且global_var不定義在堆棧中,而是聲明在bss中,定義在initialed data區(qū)域中
static
static也是全局但是其作用域不是全局而是本文件中,所以其他的文件include一個(gè)含有static的頭文件,且試圖定義他會(huì)報(bào)錯(cuò),因?yàn)閟tatic變量的作用域只在聲明他的頭文件中
還是上述的程序但是我們把extern改為static了var.h
static int global_var;
var.c
#include "var.h" #include "prog1.h" //function declarations,我們示例中沒(méi)有將函數(shù)原型頭文件寫(xiě)出來(lái) int global_var = 33; int increment(void) { return global_variable++ }
main.c
#include "var.h" #include "prog1.h" #include <stdio.h> //注意我們沒(méi)有include file1.c void use_it(void){ printf("global var : %d\n",global_var++); }
開(kāi)始編譯發(fā)現(xiàn)錯(cuò)誤
c++ static members in class
簡(jiǎn)而言之就是我們的class里面搞一個(gè)static的成員,我們知道static的作用域雖然是全局只存在于本文件,那么將一個(gè)static放在一個(gè)class中間是什么意思呢?
在Cpp的類(lèi)中使用static就不再和C一樣局限于定義的文件中了,在Cpp的class中用static修飾成員有以下的特點(diǎn)
- 當(dāng)這個(gè)class建立的時(shí)候,此class內(nèi)的static成員在只有一份,無(wú)論創(chuàng)建多少個(gè)class對(duì)象,且每個(gè)對(duì)象都是共享這個(gè)static成員的,換句話說(shuō)無(wú)論多少個(gè)對(duì)象創(chuàng)建,class的static成員都是第一無(wú)二的,且內(nèi)存中只有一份
- static成員的初始化發(fā)生在此class所有對(duì)象創(chuàng)建前
- 他的聲明周期是全程序
我們寫(xiě)一個(gè)程序,寫(xiě)一個(gè)class,在其public中搞一個(gè)static member,且在class的構(gòu)造函數(shù)中對(duì)這個(gè)static member + 1,意味著此static成員作用是統(tǒng)計(jì)有多少個(gè)class對(duì)象成員
static_mamber.h
using namespace std; class Box{ public: static int objcount; Box(double l,double b, double h); double volume(); private: double length; double breadth; double height; };
static_member.cpp
#include "static_member.h" #include <iostream> using namespace std; int Box::objcount = 0; //static成員的初始化在創(chuàng)建所有的class對(duì)象之前 //構(gòu)造函數(shù) Box::Box(double l, double b, double h) :length(l),breadth(b),height(h){ cout << "construct is called," << endl; objcount++; } double Box::volume(){ return length * breadth * height; }
main.cpp
#include "static_member.h" #include <iostream> using namespace std; int main(void){ Box Box1(3.3,1.2,1.5); Box Box2(8.5,6.0,2.0); cout << "total Box object is "<< Box::objcount << endl; return 0; }
編譯
g++ static_member.cpp main.cpp -o static_member.o
得到結(jié)果
construct is called,
construct is called,
total Box object is 2
注意class是全局的也就是extern的因?yàn)樵谒衎lock(
{}
)外部的變量或者class或者函數(shù)如果不加static都默認(rèn)是extern
總結(jié)
在C語(yǔ)言中extern修飾后的變量或者函數(shù),可以在其他的文件中進(jìn)行使用(需要include定義extern變量或者函數(shù)的頭文件),但是static則不行,static和extern的作用域都是全局但是,static只允許本文件內(nèi)對(duì)其修飾的變量更改,而extern允許在任何文件中更改
在C++中static修飾的是某個(gè)class的一個(gè)成員,和C中的static完全不一樣,首先C++中如果在頭文件中聲明某個(gè)class的某個(gè)成員是static,那么我們?cè)谄渌募?strong>可以定義他(前提include對(duì)于的頭文件),這是在C中是不行的,且C++ static member in clss意思是為此class創(chuàng)建一個(gè)獨(dú)一無(wú)二的成員,不論你的class實(shí)例化多少次,static成員就一個(gè),其他的class對(duì)象都是其copy,并且我們可以隨時(shí)隨地修改這個(gè)static成員
到此這篇關(guān)于C/C++ extern和static的使用的文章就介紹到這了,更多相關(guān)C++ extern和static使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++數(shù)據(jù)結(jié)構(gòu)之實(shí)現(xiàn)循環(huán)順序隊(duì)列
這篇文章主要介紹了 C++數(shù)據(jù)結(jié)構(gòu)之實(shí)現(xiàn)循環(huán)順序隊(duì)列的相關(guān)資料,需要的朋友可以參考下2017-01-01Java?C++?算法題解leetcode652尋找重復(fù)子樹(shù)
這篇文章主要為大家介紹了Java?C++?算法題解leetcode652尋找重復(fù)子樹(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09C++實(shí)戰(zhàn)之二進(jìn)制數(shù)據(jù)處理與封裝
在電腦上一切數(shù)據(jù)都是通過(guò)二進(jìn)制(0或1)進(jìn)行存儲(chǔ)的,通過(guò)多位二進(jìn)制數(shù)據(jù)可以進(jìn)而表示整形、浮點(diǎn)型、字符、字符串等各種基礎(chǔ)類(lèi)型數(shù)據(jù)或者一些更復(fù)雜的數(shù)據(jù)格式。本文將為大家詳細(xì)講講二進(jìn)制數(shù)據(jù)處理與封裝,需要的可以參考一下2022-08-08Qt實(shí)現(xiàn)編輯數(shù)據(jù)庫(kù)數(shù)據(jù)的方法詳解
這篇文章主要為大家詳細(xì)介紹了Qt是如何實(shí)現(xiàn)編輯數(shù)據(jù)庫(kù)數(shù)據(jù)的,文中的示例代碼簡(jiǎn)潔易懂,對(duì)我們深入了解QT有一定的幫助,感興趣的小伙伴可以了解一下2023-02-02漫畫(huà)講解C語(yǔ)言中最近公共祖先的三種類(lèi)型
這篇文章主要總結(jié)了使用C語(yǔ)言查找最近公共祖先的三種方法類(lèi)型,用漫畫(huà)的方式講解原理定義,看上去更生動(dòng)形象,幫助你更好的理解透徹,快來(lái)跟著本文往下看吧2021-11-11淺談返回函數(shù)內(nèi)部new分配的內(nèi)存的引用
下面小編就為大家?guī)?lái)一篇淺談返回函數(shù)內(nèi)部new分配的內(nèi)存的引用。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12