最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言中volatile關(guān)鍵字的作用及說明

 更新時(shí)間:2024年10月29日 14:31:05   作者:萊特昂  
文中主要介紹了C語言中volatile關(guān)鍵字的含義和使用場景,volatile是一個(gè)類型修飾符,主要用來修飾被不同線程訪問和修改的變量,它的作用是防止編譯器對(duì)代碼進(jìn)行優(yōu)化,確保每次直接讀取原始內(nèi)存地址的值

volatile關(guān)鍵字的作用

在看C語言基礎(chǔ)知識(shí)的時(shí)候看到了volatile關(guān)鍵字,不是很理解,所以查了資料,總結(jié)一下。

volatile譯為:易變的

  • volatile是一個(gè)類型修飾符(type specifier),就像我們熟悉的const一樣,它是被設(shè)計(jì)用來修飾被不同線程訪問和修改的變量;
  • volatile的作用是作為指令關(guān)鍵字,確保本條指令不會(huì)因編譯器的優(yōu)化而省略,且要求每次直接讀值。

簡單地說就是防止編譯器對(duì)代碼進(jìn)行優(yōu)化。

比如如下程序:

XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;

對(duì)外部硬件而言,上述四條語句分別表示不同的操作,會(huì)產(chǎn)生四種不同的動(dòng)作,但是編譯器卻會(huì)對(duì)上述四條語句進(jìn)行優(yōu)化,認(rèn)為只有XBYTE[2]=0x58(即忽略前三條語句,只產(chǎn)生一條機(jī)器代碼)。

如果鍵入volatile,則編譯器會(huì)逐一地進(jìn)行編譯并產(chǎn)生相應(yīng)的機(jī)器代碼(產(chǎn)生四條代碼)。

典型的例子

for(int i=0; i<100000; i++);

這個(gè)語句用來測試空循環(huán)的速度的

但是編譯器肯定要把它優(yōu)化掉,根本就不執(zhí)行

如果你寫成

for(volatile int i=0; i<100000; i++);

它就會(huì)執(zhí)行了

volatile的本意是“易變的”

下面是volatile變量的幾個(gè)例子:

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

2)一個(gè)中斷服務(wù)子程序中會(huì)訪問到的非自動(dòng)變量(Non-automatic variables)

3)多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量

一些相關(guān)的面試題

1)一個(gè)參數(shù)既可以是const還可以是volatile嗎?解釋為什么。

2)一個(gè)指針可以是volatile 嗎?解釋為什么。

3)下面的函數(shù)被用來計(jì)算某個(gè)整數(shù)的平方,它能實(shí)現(xiàn)預(yù)期設(shè)計(jì)目標(biāo)嗎?如果不能,試回答存在什么問題:

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

下面是答案:

1)是的。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖?。它是const因?yàn)槌绦虿粦?yīng)該試圖去修改它。

2)是的。盡管這并不很常見。一個(gè)例子是當(dāng)一個(gè)中斷服務(wù)子程序修改一個(gè)指向一個(gè)buffer的指針時(shí)。

3)這段代碼是個(gè)惡作劇。這段代碼的目的是用來返指針ptr指向值的平方,但是,由于ptr指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼:

int square(volatile int* &ptr)//這里參數(shù)應(yīng)該申明為引用,不然函數(shù)體里只會(huì)使用副本,外部沒法更改

{
    int a,b;
    a = *ptr;
    b = *ptr;
    return a*b;
}

由于ptr的值可能在兩次取值語句之間發(fā)生改變,因此a和b可能是不同的。

結(jié)果,這段代碼可能返回的不是你所期望的平方值!

正確的代碼如下:

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

另外,還可能出現(xiàn)在debug版中看不出來,在release版中才顯現(xiàn)的問題:

#include<stdio.h>
void main(int argc,char *argv[])
{
 int i = 10;
 int a = i;
 printf("i=%d",a);
 //下面匯編語句的作用就是改變內(nèi)存中i的值,但是又不讓編譯器知道
__asm
    {
        mov dword ptr[ebp-4],20h
    }
    int b = i;
    printf("i=%d",b);
}

然后,在調(diào)試版本模式運(yùn)行程序,輸出結(jié)果如下:

i = 10
i = 32

然后,在release版本模式運(yùn)行程序,輸出結(jié)果如下:

i = 10
i = 10

輸出的結(jié)果明顯表明,release模式下,編譯器對(duì)代碼進(jìn)行了優(yōu)化,第二次沒有輸出正確的i值。

我們把 i的聲明加上volatile關(guān)鍵字,看看有什么變化:

#include<stdio.h>
void main(int argc,char *argv[])
{
    volatile int i = 10;
    int a = i;
    printf("i=%d",a);
    __asm
    {
    `    mov dword ptr[ebp-4],20h
    }
    int b = i;
    printf("i=%d",b);
}

分別在調(diào)試版本和release版本運(yùn)行程序,輸出都是:

i = 10
i = 32

這說明這個(gè)關(guān)鍵字發(fā)揮了它的作用!

volatile應(yīng)該解釋為“直接存取原始內(nèi)存地址”比較合適,“易變的”這種解釋簡直有點(diǎn)誤導(dǎo)人;

比如多線程的程序,共同訪問的內(nèi)存當(dāng)中,多個(gè)程序都可以操縱這個(gè)變量

你自己的程序,是無法判定何時(shí)這個(gè)變量會(huì)發(fā)生變化

還比如,他和一個(gè)外部設(shè)備的某個(gè)狀態(tài)對(duì)應(yīng),當(dāng)外部設(shè)備發(fā)生操作的時(shí)候,通過驅(qū)動(dòng)程序和中斷事件,系統(tǒng)改變了這個(gè)變量的數(shù)值,而你的程序并不知道。

對(duì)于volatile類型的變量,系統(tǒng)每次用到他的時(shí)候都是直接從對(duì)應(yīng)的內(nèi)存當(dāng)中提取,而不會(huì)利用cache當(dāng)中的原有數(shù)值,以適應(yīng)它的未知何時(shí)會(huì)發(fā)生的變化,系統(tǒng)對(duì)這種變量的處理不會(huì)做優(yōu)化——顯然也是因?yàn)樗臄?shù)值隨時(shí)都可能變化的情況。

使用地方

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

1、中斷服務(wù)程序中修改的供其它程序檢測的變量需要加volatile;

2、多任務(wù)環(huán)境下各任務(wù)間共享的標(biāo)志應(yīng)該加volatile;

3、存儲(chǔ)器映射的硬件寄存器通常也要加volatile說明,因?yàn)槊看螌?duì)它的讀寫都可能有不同意義;

另外,以上這幾種情況經(jīng)常還要同時(shí)考慮數(shù)據(jù)的完整性(相互關(guān)聯(lián)的幾個(gè)標(biāo)志讀了一半被打斷了重寫),在1中可以通過關(guān)中斷來實(shí)現(xiàn),2 中可以禁止任務(wù)調(diào)度,3中則只能依靠硬件的良好設(shè)計(jì)了。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C語言內(nèi)存函數(shù)的具體使用

    C語言內(nèi)存函數(shù)的具體使用

    本文介紹了C語言中幾個(gè)常用的內(nèi)存函數(shù),包括memcpy、memmove、memset、memcmp的使用方法及其模擬實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11
  • 一文詳解QDialog中exec與open的區(qū)別

    一文詳解QDialog中exec與open的區(qū)別

    這篇文章主要為大家詳細(xì)介紹了QDialog中exec與open的區(qū)別,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Qt有一定的幫助,需要的可以參考一下
    2023-03-03
  • C語言中char*和char[]用法區(qū)別分析

    C語言中char*和char[]用法區(qū)別分析

    這篇文章主要介紹了C語言中char*和char[]用法區(qū)別,包括使用過程中的誤區(qū)及注意點(diǎn)分析,需要的朋友可以參考下
    2014-09-09
  • C語言文件操作實(shí)現(xiàn)數(shù)據(jù)持久化(幫你快速了解文件操作函數(shù))

    C語言文件操作實(shí)現(xiàn)數(shù)據(jù)持久化(幫你快速了解文件操作函數(shù))

    持久數(shù)據(jù)其實(shí)就是將數(shù)據(jù)保存到數(shù)據(jù)庫,下面這篇文章主要給大家介紹了關(guān)于C語言文件操作實(shí)現(xiàn)數(shù)據(jù)持久化(幫你快速了解文件操作函數(shù))的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • C++ sort排序函數(shù)用法詳解

    C++ sort排序函數(shù)用法詳解

    本文主要介紹了C++ sort排序函數(shù)用法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 基于重啟后消失的注冊表鍵值的詳細(xì)介紹

    基于重啟后消失的注冊表鍵值的詳細(xì)介紹

    本篇文章是對(duì)重啟后消失的注冊表鍵值進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • Qt Designer的簡單使用方法

    Qt Designer的簡單使用方法

    用 C++ 代碼編寫圖形界面的問題就是不直觀,因此 Qt 項(xiàng)目開發(fā)了專門的可視化圖形界面編輯器,本文就詳細(xì)的介紹一下
    2021-08-08
  • do...while(0)的妙用詳細(xì)解析

    do...while(0)的妙用詳細(xì)解析

    do...while(0)消除goto語句;通常,如果在一個(gè)函數(shù)中開始要分配一些資源,然后在中途執(zhí)行過程中如果遇到錯(cuò)誤則退出函數(shù),當(dāng)然,退出前先釋放資源
    2013-09-09
  • C++操作json文件以及jsoncpp配置詳解

    C++操作json文件以及jsoncpp配置詳解

    這篇文章主要給大家介紹了關(guān)于C++操作json文件以及jsoncpp配置的相關(guān)資料,文中通過實(shí)例代碼及圖片介紹的非常詳細(xì),需要的朋友可以參考下
    2021-06-06
  • C++(STL庫)之順序容器vector的使用

    C++(STL庫)之順序容器vector的使用

    這篇文章主要介紹了C++(STL庫)之順序容器vector的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02

最新評(píng)論

岱山县| 剑河县| 乡宁县| 和顺县| 庆云县| 天全县| 甘德县| 杭锦旗| 南靖县| 大冶市| 汉源县| 安福县| 光山县| 龙州县| 罗定市| 文昌市| 伊春市| 容城县| 香港| 大新县| 庆安县| 盖州市| 松原市| 乌兰浩特市| 西宁市| 日喀则市| 岚皋县| 稻城县| 平阴县| 曲沃县| 南召县| 青浦区| 景东| 景洪市| 商河县| 渝中区| 辛集市| 南江县| 八宿县| 武平县| 太白县|