亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

深入理解C++中變量的存儲類別和屬性

2020-01-26 14:53:10
字體:
來源:轉載
供稿:網友

C++變量的存儲類別(動態存儲、靜態存儲、自動變量、寄存器變量、外部變量)
動態存儲方式與靜態存儲方式

我們已經了解了變量的作用域。作用域是從空間的角度來分析的,分為全局變量和局部變量。

變量還有另一種屬性――存儲期(storage duration,也稱生命期)。存儲期是指變量在內存中的存在期間。這是從變量值存在的時間角度來分析的。存儲期可以分為靜態存儲期(static storage duration)和動態存儲期(dynamic storage duration)。這是由變量的靜態存儲方式和動態存儲方式決定的。

所謂靜態存儲方式是指在程序運行期間,系統對變量分配固定的存儲空間。而動態存儲方式則是在程序運行期間,系統對變量動態地分配存儲空間。

先看一下內存中的供用戶使用的存儲空間的情況。這個存儲空間可以分為三部分,即:

  1. 程序區
  2. 靜態存儲區
  3. 動態存儲區


數據分別存放在靜態存儲區和動態存儲區中。全局變量全部存放在靜態存儲區中,在程序開始執行時給全局變量分配存儲單元,程序執行完畢就釋放這些空間。在程序執行過程中它們占據固定的存儲單元,而不是動態地進行分配和釋放。

在動態存儲區中存放以下數據:
函數形式參數。在調用函數時給形參分配存儲空間。
函數中的自動變量(未加static聲明的局部變量,詳見后面的介紹)。
函數調用時的現場保護和返回地址等。

對以上這些數據,在函數調用開始時分配動態存儲空間,函數結束時釋放這些空間。在程序執行過程中,這種分配和釋放是動態的,如果在一個程序中兩次調用同一函數,則要進行兩次分配和釋放,而兩次分配給此函數中局部變量的存儲空間地址可能是不相同的。

如果在一個程序中包含若干個函數,每個函數中的局部變量的存儲期并不等于整個程序的執行周期,它只是整個程序執行周期的一部分。根據函數調用的情況,系統對局部變量動態地分配和釋放存儲空間。

在C++中變量除了有數據類型的屬性之外,還有存儲類別(storage class) 的屬性。存儲類別指的是數據在內存中存儲的方法。存儲方法分為靜態存儲和動態存儲兩大類。具體包含4種:自動的(auto)、靜態的(static)、寄存器的(register)和外部的(extern)。根據變量的存儲類別,可以知道變量的作用域和存儲期。
自動變量

函數中的局部變量,如果不用關鍵字static加以聲明,編譯系統對它們是動態地分配存儲空間的。函數的形參和在函數中定義的變量(包括在復合語句中定義的變量)都屬此類。在調用該函數時,系統給形參和函數中定義的變量分配存儲空間,數據存儲在動態存儲區中。在函數調用結束時就自動釋放這些空間。如果是在復合語句中定義的變量,則在變量定義時分配存儲空間,在復合語句結束時自動釋放空間。因此這類局部變量稱為自動變量(auto variable)。自動變量用關鍵字auto作存儲類別的聲明。例如:

int f(int a) //定義f函數,a為形參{  auto int b, c=3; //定義b和c為整型的自動變量}

存儲類別auto和數據類型int的順序任意。關鍵字auto可以省略,如果不寫auto,則系統把它默認為自動存儲類別,它屬于動態存儲方式。程序中大多數變量屬于自動變量。本教程前面各章所介紹的例子中,在函數中定義的變量都沒有聲明為auto,其實都默認指定為自動變量。在函數體中以下兩種寫法作用相同:

auto int b, c=3;int b, c=3;


用static聲明靜態局部變量

有時希望函數中的局部變量的值在函數調用結束后不消失而保留原值,即其占用的存儲單元不釋放,在下一次該函數調用時,該變量保留上一次函數調用結束時的值。這時就應該指定該局部變量為靜態局部變量(static local variable)。

【例】靜態局部變量的值。

#include <iostream>using namespace std;int f(int a) //定義f函數,a為形參{  auto int b=0; //定義b為自動變量  static int c=3; //定義c為靜態局部變量  b=b+1;  c=c+1;  return a+b+c;}int main( ){  int a=2,i;  for(i=0;i<3;i++)  cout<<f(a)<<" ";  cout<<endl;  return 0;}

運行結果為:

7 8 9

先后3次調用f函數時,b和c的值如表所示。


對靜態局部變量的說明:
靜態局部變量在靜態存儲區內分配存儲單元。在程序整個運行期間都不釋放。而自動變量(即動態局部變量)屬于動態存儲類別,存儲在動態存儲區空間(而不是靜態存儲區空間),函數調用結束后即釋放。
為靜態局部變量賦初值是在編譯時進行值的,即只賦初值一次,在程序運行時它已有初值。以后每次調用函數時不再重新賦初值而只是保留上次函數調用結束時的值。而為自動變量賦初值,不是在編譯時進行的,而是在函數調用時進行,每調用一次函數重新給一次初值,相當于執行一次賦值語句。
如果在定義局部變量時不賦初值的話,對靜態局部變量來說,編譯時自動賦初值0(對數值型變量)或空字符(對字符型變量)。而對自動變量來說,如果不賦初值,則它的值是一個不確定的值。這是由于每次函數調用結束后存儲單元已釋放,下次調用時又重新另分配存儲單元,而所分配的單元中的值是不確定的。
雖然靜態局部變量在函數調用結束后仍然存在,但其他函數是不能引用它的,也就是說,在其他函數中它是“不可見”的。

在什么情況下需要用局部靜態變量呢?

1) 需要保留函數上一次調用結束時的值。例如可以用下例中的方法求n!。

【例】輸出1~5的階乘值(即1!,2!,3!,4!,5!)。

#include <iostream>using namespace std;int fac(int); //函數聲明int main( ){  int i;  for(i=1;i<=5;i++)   cout<<i<<"!="<<fac(i)<<endl;  return 0;}int fac(int n){  static int f=1; //f為靜態局部變量,函數結束時f的值不釋放  f=f*n; //在f原值基礎上乘以n  return f;}

運行結果為

1!=12!=23!=64!=245!=120


每次調用fac(i),就輸出一個i,同時保留這個i!的值,以便下次再乘(i+1)。

2) 如果初始化后,變量只被引用而不改變其值,則這時用靜態局部變量比較方便,以免每次調用時重新賦值。 但是應該看到,用靜態存儲要多占內存,而且降低了程序的可讀性,當調用次數多時往往弄不清靜態局部變量的當前值是什么。因此,如不必要,不要多用靜態局部變量。
用register聲明寄存器變量

一般情況下,變量的值是存放在內存中的。當程序中用到哪一個變量的值時,由控制器發出指令將內存中該變量的值送到CPU中的運算器。經過運算器進行運算,如果需要存數,再從運算器將數據送到內存存放。如圖所示。


為提高執行效率,C++允許將局部變量的值放在CPU中的寄存器中,需要用時直接從寄存器取出參加運算,不必再到內存中去存取。這種變量叫做寄存器變量,用關鍵字register作聲明。例如,可以將例4.14中的fac函數改寫如下:

int fac(int n){  register int i,f=1; //定義i和f是寄存器變量  for(i=1;i<=n;i++) f=f*i;  return f;}

定義f和i是存放在寄存器的局部變量,如果n的值大,則能節約許多執行時間。

在程序中定義寄存器變量對編譯系統只是建議性(而不是強制性)的。當今的優化編譯系統能夠識別使用頻繁的變量,自動地將這些變量放在寄存器中。
用extern聲明外部變量

全局變量(外部變量)是在函數的外部定義的,它的作用域為從變量的定義處開始,到本程序文件的末尾。在此作用域內,全局變量可以為本文件中各個函數所引用。編譯時將全局變量分配在靜態存儲區。

有時需要用extern來聲明全局變量,以擴展全局變量的作用域。

1) 在一個文件內聲明全局變量
如果外部變量不在文件的開頭定義,其有效的作用范圍只限于定義處到文件終了。如果在定義點之前的函數想引用該全局變量,則應該在引用之前用關鍵字extern對該變量作外部變量聲明,表示該變量是一個將在下面定義的全局變量。有了此聲明,就可以從聲明處起,合法地引用該全局變量,這種聲明稱為提前引用聲明。

【例】用extern對外部變量作提前引用聲明,以擴展程序文件中的作用域。

#include <iostream>using namespace std;int max(int,int); //函數聲明void main( ){  extern int a,b;//對全局變量a,b作提前引用聲明  cout<<max(a,b)<<endl;}int a=15,b=-7;//定義全局變量a,bint max(int x,int y){  int z;  z=x>y?x:y;  return z;}

運行結果如下:

15

在main后面定義了全局變量a,b,但由于全局變量定義的位置在函數main之后,因此如果沒有程序的第5行,在main函數中是不能引用全局變量a和b的。現在我們在main函數第2行用extern對a和b作了提前引用聲明,表示a和b是將在后面定義的變量。這樣在main函數中就可以合法地使用全局變量a和b了。如果不作extern聲明,編譯時會出錯,系統認為a和b未經定義。一般都把全局變量的定義放在引用它的所有函數之前,這樣可以避免在函數中多加一個extern聲明。

2) 在多文件的程序中聲明外部變量
如果一個程序包含兩個文件,在兩個文件中都要用到同一個外部變量num,不能分別在兩個文件中各自定義一個外部變量num。正確的做法是:在任一個文件中定義外部變量num,而在另一文件中用extern對num作外部變量聲明。即
 

  extern int num;


編譯系統由此知道num是一個已在別處定義的外部變量,它先在本文件中找有無外部變量num,如果有,則將其作用域擴展到本行開始(如上節所述),如果本文件中無此外部變量,則在程序連接時從其他文件中找有無外部變量num,如果有,則把在另一文件中定義的外部變量num的作用域擴展到本文件,在本文件中可以合法地引用該外部變量num。

分析下例:
filel.cpp

extern int a,b;int main(){  cout<<a<<","<<b<<end!;  return 0;}file2.cppint as3,b=4;

在源程序文件ffle2.cpp中定義了整型變量a和b,并亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

91网站在线看| 97精品一区二区视频在线观看| 国产精品视频免费在线| 亚洲精品av在线播放| 欧美激情视频给我| 日韩精品视频在线| 久久亚洲影音av资源网| 亚洲国产天堂久久综合网| 538国产精品视频一区二区| 亚洲久久久久久久久久久| 亚洲精品福利免费在线观看| 懂色av中文一区二区三区天美| 国产成人精品久久二区二区| 亚洲精品一区中文字幕乱码| 久久精品成人动漫| 91精品国产99久久久久久| 66m—66摸成人免费视频| 欧美日韩美女在线观看| 日韩av色在线| 日韩精品中文字幕在线观看| 81精品国产乱码久久久久久| 日韩av观看网址| 亚洲免费视频网站| 精品五月天久久| 伊人久久久久久久久久久久久| 国产91在线播放九色快色| 亚洲欧美国产精品久久久久久久| 久久99国产精品久久久久久久久| 欧美激情videos| 91亚洲精品一区二区| 欧美精品免费播放| 亚洲一区美女视频在线观看免费| 亚洲毛片在线观看| 5278欧美一区二区三区| 亚洲一区二区中文字幕| 欧美日韩精品在线| 亚洲系列中文字幕| 精品久久久久久久久国产字幕| 亚洲999一在线观看www| 久久精品亚洲精品| 在线视频欧美日韩| 日韩有码在线视频| 色综合久综合久久综合久鬼88| 久久成年人视频| 欧美性高跟鞋xxxxhd| 国内精品美女av在线播放| 国产a∨精品一区二区三区不卡| 精品国产91乱高清在线观看| 国产精品福利在线观看网址| 欧美电影在线播放| 精品国产一区二区在线| 2019中文在线观看| 北条麻妃一区二区在线观看| 久久99热精品这里久久精品| 日韩欧美国产网站| 国产精品久久久999| 亚洲午夜精品久久久久久性色| 91精品国产乱码久久久久久蜜臀| 91精品视频一区| www.久久草.com| 中文字幕亚洲色图| 久久深夜福利免费观看| 亚洲人a成www在线影院| 91社影院在线观看| 久久久久在线观看| 精品视频在线观看日韩| 色狠狠久久aa北条麻妃| 国产精品69av| 伊人久久久久久久久久久久久| 91av在线播放| 久久久av电影| 国产视频丨精品|在线观看| 中文字幕日韩综合av| 中文字幕日韩精品在线| 欧美三级欧美成人高清www| 黄色精品在线看| 91九色精品视频| 国产mv免费观看入口亚洲| 亚洲一区二区三区乱码aⅴ蜜桃女| 亚洲美女av电影| 亚洲人成在线免费观看| 日韩美女激情视频| 国产精品亚洲网站| 久久久av网站| 亚洲综合中文字幕在线观看| 日韩高清a**址| 国产欧美日韩综合精品| 欧美一区二区三区精品电影| 正在播放国产一区| 97在线观看视频国产| 国产婷婷色综合av蜜臀av| 亚洲一区二区三区xxx视频| 亚洲精品美女免费| 国产丝袜精品第一页| 97国产在线观看| 国产网站欧美日韩免费精品在线观看| 疯狂做受xxxx高潮欧美日本| 亚洲欧美福利视频| 精品亚洲va在线va天堂资源站| 久久色在线播放| 欧美成人午夜激情在线| 日韩美女视频中文字幕| 丰满岳妇乱一区二区三区| 亚洲精品视频播放| 日韩在线视频网站| 国产精品91在线观看| 97色在线视频观看| 亚洲a级在线观看| 日韩欧美一区二区三区久久| 91在线精品视频| 国产剧情日韩欧美| 91美女片黄在线观看游戏| 日韩欧美国产高清91| 中文字幕亚洲一区二区三区五十路| 欧美大片在线影院| 国产精品嫩草影院一区二区| 98视频在线噜噜噜国产| 日韩在线www| 亚洲男人天堂网站| 亚洲精品suv精品一区二区| 欧美激情性做爰免费视频| 97视频在线观看免费高清完整版在线观看| 久久亚洲精品一区二区| 性金发美女69hd大尺寸| www.99久久热国产日韩欧美.com| 色在人av网站天堂精品| 欧美一区深夜视频| 亚洲情综合五月天| 亚洲国产精品人人爽夜夜爽| 68精品国产免费久久久久久婷婷| 成人在线精品视频| 欧美一区二区三区四区在线| 国产精品成人一区二区三区吃奶| 亚洲开心激情网| 亚洲品质视频自拍网| 国产成人精品午夜| 亚洲精品小视频在线观看| 欧美性少妇18aaaa视频| 粉嫩老牛aⅴ一区二区三区| 亚洲日韩欧美视频| 亚洲美女精品成人在线视频| 亚洲石原莉奈一区二区在线观看| 麻豆国产va免费精品高清在线| 亚洲欧美另类在线观看| 97热在线精品视频在线观看| 97免费视频在线播放| 在线观看成人黄色| 午夜欧美大片免费观看| 色婷婷综合成人av| 欧美亚洲国产日本| 91麻豆桃色免费看| 性欧美xxxx视频在线观看| 欧美精品在线看| 日韩电影大全免费观看2023年上| 日韩av一区二区在线观看| 国产精品网站大全| 欧美重口另类videos人妖| 精品久久中文字幕久久av| 少妇高潮久久久久久潘金莲| 欧美电影免费观看高清| 美日韩精品免费视频| 欧美大片大片在线播放| 51色欧美片视频在线观看| 国产精品久久久av|