全局變量不受作用域影響 如果在一個文件中使用extern關鍵字來聲明另一個文件中存在的全局變量,那么這個文件可以使用這個數據(即另一個文件中使用已存在文件中的變量,兩者共用一個變量)
//**test1.cpp:**#include <iostream>using namespace std;//聲明int globe;void f();int main(){ globe=12; cout<<globe<<std::endl; f(); cout<<globe<<std::endl; return 0;}//**test2.cpp**extern int globe;void f(){ globe=47;}test1.cpp和test2.cpp是分段編譯的,必須通過聲明extern int globe來告訴編譯器變量存在哪里。 創建后的程序,帶有test2的目標文件必須被連接起來,test2 不會生成可執行文件,編譯它是為了把它連接進來其他的可執行文件中。
局部變量出現在一個作用域內,他們是局限于一個函數的,局部變量被稱為自動變量,因為它們在進入作用域時自動生成,離開作用域時在自動消失,關鍵字auto可以顯示的說明這個問題,但是局部變量默認為auto,所以沒有必要聲明為auto 寄存器變量:是一種局部變量,關鍵字register告訴編譯器“盡可能快的訪問這個變量”,加快訪問速度取決于實現,通常通過在寄存器中放置變量來實現。–>并不保證一定將變量放在寄存器中,甚至不能保證提高訪問速度,這只是對編譯器的一個請求或暗示。
1、局部變量用static修飾,即可以使得局部變量的值在整個程序的生命周期中里仍然存在。
#include <iostream>using namespace std;void func(){ static int i=0; cout<<"i = "<<i++<<std::endl;}int main(){ for(int x=0;x<10;x++){ func(); } return 0;}2、當應用static于函數名和所有函數外部的變量時,它的意思是“在文件的外部不可以使用這個名字”即函數名或變量是局部于文件的,所以static具有文件作用域。即使被聲明為extern,連接器也不會找到該變量,用了static之后,該變量僅限于在本cpp中使用。
extern關鍵字:告訴編譯器存在著一個變量和函數,即使編譯器在當前編譯的文件中沒有看到它。這個變量或函數可能在另一個文件中或者在當前文件的后面定義。 如下圖例子:extern int i其實不是定義變量,而是告訴編譯器,該變量會在當前文件后面或者另一個文件中已經定義了。
#include <iostream>using namespace std;extern int i;extern void func();//extern關鍵字:這個變量或函數可能在另一個文件中或者在當前文件的后面定義。int main(){ i=0; func();}int i;//數據定義void func(){ i++; cout<<i;}在舊版本的C中,如果相建立一個常量,必須使用預處理器
#define PI 3.1415926;`對名字PI不會進行類型檢查(即預處理之后程序中遇到PI的就換成3.1415926,預處理定義常量無需寫是什么類型的數據),也不能得到PI的地址(所以不能向PI傳傳遞一個指針和一個引用),PI不能是用戶定義的類型變量。預處理器并不識別作用域(預處理即為預先處理,在程序編譯之前就進行了,所以沒有啥作用域)。
使用const關鍵字 const就像正常的變量一樣有作用域。 在C中定義const時,如果咋兩個不同的文件中(或在頭文件中),定義多個同名的const,編譯器將生成發生沖突的錯誤消息。 在C中使用const和在C++中使用是完全不一樣的,在C++中使用更好。 在C++中,const變量必須有初始值(在C中不是這樣),內部類型的常量值可以表示為十進制、八進制、十六進制、浮點數或字符 常量值錢帶0:八進制 常量值錢帶0x:十六進制 浮點數可以含有小數或指數冪(用e表示,意思是10的冪)
volatile告訴編譯器“不知道何時會改變”,防止編譯器依據變量的穩定性作任何優化 如果一個標識符是voliate的,編譯器不會認為它能夠對標識符的多次讀入進行優化,即多線程讀取一個數據時,會觀察該數據是否正在被另一個標識符或進程修改,即為保證可見性,是輕量級的同步,保證每次都從內存中讀取數據。
java中的volatile volatile和synchronize有本質的區別
用一句話概括volatile,它能夠使變量在值發生改變時能盡快地讓其他線程知道.同步:如用synchronized關鍵字,或者使用鎖對象.volatile關鍵字保證的是可見性,是字段關鍵字,不像synchronize還可以修飾方法和類。 volatile關鍵字保證字段每次都是從堆內存中讀取,當字段在棧中進行多線程操作時,隨機進入的每個線程必須從堆內存中讀取該字段到棧中進行操作,操作完成再放回堆中,這樣就可以保證每個線程讀取到的字段是最新值。 (個人理解:volatile關鍵字讓字段像引用類型數據一樣,存放在堆中,讓原本在多線程環境下字段copy給每個線程使用的,變成了線程都得從堆中尋址字段。一般一個類的基本類型數據操作時就是把數據copy給線程棧使用的,而加了volatile之后,就直接像引用類型一樣操作了。)
首先我們要先意識到有這樣的現象,編譯器為了加快程序運行的速度,對一些變量的寫操作會先在寄存器或者是CPU緩存上進行,最后才寫入內存. 而在這個過程,變量的新值對其他線程是不可見的.而volatile的作用就是使它修飾的變量的讀寫操作都必須在內存中進行!
volatile本質是在告訴jvm當前變量在寄存器中的值是不確定的,需要從主存中讀取,synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住.volatile僅能使用在變量級別,synchronized則可以使用在變量,方法.volatile僅能實現變量的修改可見性,但不具備原子特性,而synchronized則可以保證變量的修改可見性和原子性.volatile不會造成線程的阻塞,而synchronized可能會造成線程的阻塞.volatile標記的變量不會被編譯器優化,而synchronized標記的變量可以被編譯器優化.所以從一定意義上說,voliate相當于輕量級的synchronize。 但不同的是,volatile關鍵字不是給字段加鎖,只是把字段讀取區域固定在主內存區并不阻塞控制線程的進入,該字段下的多線程環境還是隨機的,并不能保證一個數據不會被多個線程并發修改(voliate關鍵字并不能控制線程等待、阻塞、喚醒等,更不能讓線程序列執行)。
synchronize關鍵字保證的就是同步互斥。 synchronize和volatile最大的區別就是是否為線程加鎖。
新聞熱點
疑難解答
圖片精選