久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C語言丨深入理解volatile關(guān)鍵字

 精品唯居 2021-05-24

本篇文章是對C語言中關(guān)鍵字volatile的含義進行了詳細的分析介紹,,希望能在學習上幫助大家。


 

volatile是一個類型修飾符(type specifier),。它是被設(shè)計用來修飾被不同線程訪問和修改的變量,。如果沒有volatile,基本上會導致這樣的結(jié)果:要么無法編寫多線程程序,,要么編譯器失去大量優(yōu)化的機會,。

1.原理作用

Volatile意思是“易變的”,應該解釋為“直接存取原始內(nèi)存地址”比較合適,?!耙鬃儭笔且驗橥庠谝蛩匾鸬模穸嗑€程,,中斷等,。

C語言書籍這樣定義volatile關(guān)鍵字:

volatile提醒編譯器它后面所定義的變量隨時都有可能改變,因此編譯后的程序每次需要存儲或讀取這個變量的時候,,告訴編譯器對該變量不做優(yōu)化,,都會直接從變量內(nèi)存地址中讀取數(shù)據(jù),從而可以提供對特殊地址的穩(wěn)定訪問,。

如果沒有volatile關(guān)鍵字,則編譯器可能優(yōu)化讀取和存儲,,可能暫時使用寄存器中的值,,如果這個變量由別的程序更新了的話,將出現(xiàn)不一致的現(xiàn)象,。(簡潔的說就是:volatile關(guān)鍵詞影響編譯器編譯的結(jié)果,,用volatile聲明的變量表示該變量隨時可能發(fā)生變化,與該變量有關(guān)的運算,不要進行編譯優(yōu)化,,以免出錯)

2.一般用處

一般說來,,volatile用在如下的幾個地方: 

1)并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)

         存儲器映射的硬件寄存器通常也要加 voliate,因為每次對它的讀寫都可能有不同意義,。

        例如:假設(shè)要對一個設(shè)備進行初始化,,此設(shè)備的某一個寄存器為0xff800000。

int *output = (unsigned int *)0xff800000;//定義一個IO端口,;

int  init(void)

{

      int i;

      for(i=0;i< 10;i++){

        *output = i;

}

}

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

int init(void)

{

*output =9;

}

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

2)中斷服務程序中修改的供其它程序檢測的變量,,需要加volatile,; 

        當變量在觸發(fā)某中斷程序中修改,而編譯器判斷主函數(shù)里面沒有修改該變量,,因此可能只執(zhí)行一次從內(nèi)存到某寄存器的讀操作,,而后每次只會從該寄存器中讀取變量副本,使得中斷程序的操作被短路,。

3)多任務環(huán)境下各任務間共享的標志,,應該加volatile; 

        在本次線程內(nèi), 當讀取一個變量時,,編譯器優(yōu)化時有時會先把變量讀取到一個寄存器中,;以后,再取變量值時,,就直接從寄存器中取值,;當內(nèi)存變量或寄存器變量在因別的線程等而改變了值,該寄存器的值不會相應改變,,從而造成應用程序讀取的值和實際的變量值不一致 ,。

4)存儲器映射的硬件寄存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義;

  假設(shè)要對一個設(shè)備進行初始化,,此設(shè)備的某一個寄存器為0xff800000,。for(i=0;i< 10;i++)  *output = i;前面循環(huán)半天都是廢話,對最后的結(jié)果毫無影響,,因為最終只是將output這個指針賦值為9,,省略了對該硬件IO端口反復讀的操作。

這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問題:嵌入式系統(tǒng)程序員經(jīng)常同硬件,、中斷,、RTOS等等打交道,所有這些都要求使用volatile變量,。不懂得volatile內(nèi)容將會帶來災難,。

3.volatile 問題和總結(jié)

volatile 常見的幾個面試題:

1)一個參數(shù)既可以是const還可以是volatile嗎?

        可以的,,例如只讀的狀態(tài)寄存器,。它是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它,。

2) 一個指針可以是volatile 嗎,?

  可以,當一個中服務子程序修改一個指向buffer的指針時,。

4.下面的函數(shù)有什么錯誤,?

int  square(volatile int*ptr)

{

    return*ptr * *ptr;

}

該程序的目的是用來返指針*ptr指向值的平方,但是,,由于*ptr指向一個volatile型參數(shù),,編譯器將產(chǎn)生類似下面的代碼:

int square(volatile int*ptr)

{

    int a,b;

    a = *ptr;

    b = *ptr;

    return a * b;

}

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

long square(volatile int*ptr)

{

    int a;

    a = *ptr;

    return a * a;

}

注意:頻繁地使用volatile很可能會增加代碼尺寸和降低性能,因此要合理的使用volatile,。

總結(jié):

volatile 關(guān)鍵字是一種類型修飾符,,用它聲明的類型變量表示可以被某些編譯器未知的因素更改。volatile 提醒編譯器它后面所定義的變量隨時都有可能改變,,因此編譯后的程序每次需要存儲或讀取這個變量的時候,,都會直接從變量地址中讀取數(shù)據(jù)。如 果沒有 volatile 關(guān)鍵字,,則編譯器可能優(yōu)化讀取和存儲,,可能暫時使用寄存器中的值,如果這個變量由別的程序更新了的話,,將出現(xiàn)不一致的現(xiàn)象。所以遇到這個關(guān)鍵字聲明的變量,編譯器對訪問該變量的代碼就不再進行優(yōu)化,,從而可以提供對特殊地址的穩(wěn)定訪問,。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多