【C++快速上手】十、volatile學習筆記

      網友投稿 853 2025-03-31

      總結


      volatile 關鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素(操作系統、硬件、其它線程等)更改。所以使用 volatile 告訴編譯器不應對這樣的對象進行優化。

      volatile 關鍵字聲明的變量,每次訪問時都必須從內存中取出值(沒有被 volatile 修飾的變量,可能由于編譯器的優化,從 CPU 寄存器中取值)

      const 可以是 volatile (如只讀的狀態寄存器)

      指針可以是 volatile

      1、volatile

      被 volatile 修飾的變量,在對其進行讀寫操作時,會引發一些可觀測的副作用。而這些可觀測的副作用,是由程序之外的因素決定的。

      2、volatile應用

      (1)并行設備的硬件寄存器(如狀態寄存器)。 假設要對一個設備進行初始化,此設備的某一個寄存器為0xff800000

      int *output = (unsigned int *)0xff800000; //定義一個IO端口; int init(void) { int i; for(i=0;i< 10;i++) { *output = i; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      經過編譯器優化后,編譯器認為前面循環半天都是廢話,對最后的結果毫無影響,因為最終只是將output這個指針賦值為 9,所以編譯器最后給你編譯編譯的代碼結果相當于:

      int init(void) { *output = 9; }

      1

      2

      3

      4

      如果你對此外部設備進行初始化的過程是必須是像上面代碼一樣順序的對其賦值,顯然優化過程并不能達到目的。反之如果你不是對此端口反復寫操作,而是反復讀操作,其結果是一樣的,編譯器在優化后,也許你的代碼對此地址的讀操作只做了一次。然而從代碼角度看是沒有任何問題的。這時候就該使用volatile通知編譯器這個變量是一個不穩定的,在遇到此變量時候不要優化。

      (2)一個中斷服務子程序中訪問到的變量

      static int i=0; int main() { while(1) { if(i) dosomething(); } } /* Interrupt service routine */ void IRS() { i=1; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      【C++快速上手】十、volatile學習筆記

      10

      11

      12

      13

      14

      15

      上面示例程序的本意是產生中斷時,由中斷服務子程序IRS響應中斷,變更程序變量i,使在main函數中調用dosomething函數,但是,由于編譯器判斷在main函數里面沒有修改過i,因此可能只執行一次對從i到某寄存器的讀操作,然后每次if判斷都只使用這個寄存器里面的“i副本”,導致dosomething永遠不會被調用。如果將變量i加上volatile修飾,則編譯器保證對變量i的讀寫操作都不會被優化,從而保證了變量i被外部程序更改后能及時在原程序中得到感知。

      (3)多線程應用中被多個任務共享的變量。

      當多個線程共享某一個變量時,該變量的值會被某一個線程更改,應該用 volatile 聲明。作用是防止編譯器優化把變量從內存裝入CPU寄存器中,當一個線程更改變量后,未及時同步到其它線程中導致程序出錯。volatile的意思是讓編譯器每次操作該變量時一定要從內存中真正取出,而不是使用已經存在寄存器中的值。示例如下:

      volatile bool bStop=false; //bStop 為共享全局變量 //第一個線程 void threadFunc1() { ... while(!bStop){...} } //第二個線程終止上面的線程循環 void threadFunc2() { ... bStop = true; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      要想通過第二個線程終止第一個線程循環,如果bStop不使用volatile定義,那么這個循環將是一個死循環,因為bStop已經讀取到了寄存器中,寄存器中bStop的值永遠不會變成FALSE,加上volatile,程序在執行時,每次均從內存中讀出bStop的值,就不會死循環了。

      是否了解volatile的應用場景是區分C/C++程序員和嵌入式開發程序員的有效辦法,搞嵌入式的家伙們經常同硬件、中斷、RTOS等等打交道,這些都要求用到volatile變量,不懂得volatile將會帶來程序設計的災難。(說的真對!)

      3、volatile常見問題

      下面的問題可以看一下面試者是不是直正了解volatile。

      1)一個參數既可以是const還可以是volatile嗎?為什么?

      可以。一個例子是只讀的狀態寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它。

      2)一個指針可以是volatile嗎?為什么?

      可以。盡管這并不常見。一個例子是當一個中斷服務子程序修該一個指向一個buffer的指針時。

      3)下面的函數有什么錯誤?

      int square(volatile int *ptr) { return *ptr * *ptr; }

      1

      2

      3

      4

      這段代碼有點變態,其目的是用來返回指針ptr指向值的平方,但是,由于ptr指向一個volatile型參數,編譯器將產生類似下面的代碼:

      int square(volatile int *ptr) { int a,b; a = *ptr; b = *ptr; return a * b; }

      1

      2

      3

      4

      5

      6

      7

      由于*ptr的值可能被意想不到地改變,因此a和b可能是不同的。結果,這段代碼可能返回的不是你所期望的平方值!正確的代碼如下:

      long square(volatile int *ptr) { int a=*ptr; return a * a; }

      1

      2

      3

      4

      5

      4、volatile使用

      #include int main(void) { const int local = 10; int *ptr = (int*) &local; printf("Initial value of local : %d \n", local); *ptr = 100; printf("Modified value of local: %d \n", local); return 0; } //輸出 Initial value of local : 10 Modified value of local: 10

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      local定義為:const volatile int local = 10;,再執行上述程序,輸出結果為:

      Initial value of local : 10 Modified value of local: 100

      1

      2

      C++ 單片機

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:工控機無法啟動的現象及檢查步驟
      下一篇:一首歌里的十個Excel問題
      相關文章
      亚洲精品动漫免费二区| 亚洲第一第二第三第四第五第六 | 亚洲成人福利在线观看| 亚洲国产成人片在线观看无码| 在线视频亚洲一区| 亚洲人成网男女大片在线播放| 亚洲电影唐人社一区二区| 91亚洲导航深夜福利| 亚洲精品高清视频| 亚洲国产精品lv| 久久久久亚洲AV无码永不| 精品亚洲成a人片在线观看少妇| 亚洲情a成黄在线观看动漫尤物| 亚洲免费精彩视频在线观看| 亚洲电影免费在线观看| 亚洲宅男永久在线| 亚洲精品资源在线| 亚洲第一区视频在线观看| 亚洲国产超清无码专区| 激情综合亚洲色婷婷五月APP| 亚洲黄色激情视频| 亚洲伊人成无码综合网 | 亚洲神级电影国语版| 亚洲国语在线视频手机在线| 久久精品国产亚洲AV网站| 亚洲精品无码精品mV在线观看| 亚洲VA中文字幕不卡无码| 国产色在线|亚洲| 国产国拍亚洲精品福利| 亚洲第一黄色网址| 中文字幕中韩乱码亚洲大片| 亚洲情XO亚洲色XO无码| 亚洲ⅴ国产v天堂a无码二区| 亚洲欧洲国产精品久久| 亚洲国产日韩精品| 国产亚洲精品第一综合| 激情综合色五月丁香六月亚洲| 亚洲成AV人片一区二区| 亚洲色偷偷av男人的天堂 | 不卡精品国产_亚洲人成在线| 亚洲中文字幕日产乱码高清app|