C語言 volatile 關鍵字在編譯優化過程中有何作用

2020-12-08 電子工程專輯


初學的讀者可能不怎麼關心編譯器優化的功能,但對於經驗豐富的工程師來說,掌握代碼優化是必備技能。


今天講述的話題就是關於代碼優化中,關鍵字volatile在優化過程中起到的作用


一、關鍵字 volatile 什麼?

volatile是一個類型修飾符(type specifier)。 


volatile的作用是作為指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值。


volatile變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。


---來自百度百科


volatile的定義,應該在(讀書學習時都看過無數遍,但我相信絕大部分人都沒有深刻理解其中含義


當你真正編程、開發項目之後,你就會進一步理解其中含義。


二、volatile關鍵字對編譯器優化的影響

我們都知道編譯器有優化代碼的功能,我們常用的集成開發環境(Keil、 IAR等)都有優化選項。


如果不使用關鍵字 volatile 申明變量,則編譯器可能會對變量的訪問並生成非預期的代碼或刪除預期的功能。


1.何時使用volatile?

常見使用volatile聲明的情況:

  • 訪問內存映射外設。

  • 在多個線程之間共享全局變量。

  • 在中斷例程或信號處理程序中訪問全局變量。


比如,在STM32代碼中:

#define __O volatile #define     __IO    volatile             

瀏覽代碼,你會發現,很多地方都使用了「__IO」,也就是volatile.


在跑系統的項目中,線程間共享的全局變量,建議都加上volatile關鍵字,這一點,很多人沒有在意。


2.不使用volatile時可能出現的問題

如果未將變量用volatile聲明,則編譯器會假定其值不能在其定義的範圍之外進行修改。


因此,編譯器可能會執行不需要的優化。這可以通過多種方式表現出來:

  • 在輪詢硬體時,代碼可能會陷入循環。

  • 多線程代碼可能會表現出奇怪的行為。

  • 優化可能會導致刪除實現故意時序延遲的代碼。


舉例:

自己寫一個延時函數:

void Delay(int Cnt){ int i;
while(Cnt--) { i++; for(i=0; i<10; i++); }}


你在不同優化等級情況下,延時時間可能會不一樣


同樣的代碼,你在Keil 和 IAR環境下編譯出來的延時時間也可能不一樣。


當然,更深入的理解就會牽涉到彙編代碼,編譯之後的彙編代碼會比較直觀的呈現差異。


【專欄】IAR系列教程

【專欄】Keil系列教程

C語言中幾種特殊標準定義和用法

關注 微信公眾號『strongerHuang』,後臺回復「1024」查看更多內容,回復「加群」按規則加入技術交流群。


長按前往圖中包含的公眾號關注

相關焦點

  • C語言之const和volatile"究極"學習
    關於const的用法,現在大概前前後後應該寫了有兩篇文章,以前學習的時候,用法體會不是那麼深刻,為啥這麼說呢,因為在學習c++的時候,會發現const關鍵字有新的玩法,關於這個新的玩法,大家可以去看最近學習總結寫的c++文章專輯。
  • Java中volatile關鍵字概覽
    一、第一章 volatile關鍵字概覽多線程下變量的不可見性概述在多線程並發執行下,多個線程修改共享的成員變量,會出現一個線程修改了共享變量的值後,另一個線程不能直接 看到該線程修改後的變量的最新值。JMM有以下規定:所有的共享變量都存儲於主內存。這裡所說的變量指的是實例變量和類變量。不包含局部變量,因為局部變量 是線程私有的,因此不存在競爭問題。每一個線程還存在自己的工作內存,線程的工作內存,保留了被線程使用的變量的工作副本。 線程對變量的所有的操作(讀,取)都必須在工作內存中完成,而不能直接讀寫主內存中的變量。
  • DSP編程技巧之17---非常「關鍵」的關鍵字
    什麼是「關鍵字」?關鍵字就是已被C語言本身使用,不能作其它用途使用的字,例如關鍵字不能用作變量名、函數名等。那「關鍵字」到底有多關鍵?簡單得說,就是如果不掌握它們的使用方法,程序就不能按照我們的設計產生預期的結果。
  • 快速上手系列-C語言之基礎篇(一)
    吃飯用的筷子,到現在我都不知道它的由來,不知道它是在什麼歷史背景下誕生的有些東西還是有必要了解一下,比如,C語言所產生的代碼運行速度比彙編語言編寫的代碼運行速度稍慢一點,但還是有得一拼,同時C語言要比彙編語言編寫的代碼可讀性高,可移植性好。
  • C/C+編程筆記:C語言編程面試常見問題,全是經典題!
    C語言的主要特徵是什麼? C是一種過程語言。C語言的主要功能包括對內存的低級訪問,簡單的關鍵字集和簡潔的樣式。這些功能使其適用於諸如作業系統或編譯器開發之類的系統編程。 i ++和++ i有什麼區別? 1)表達式「 i ++」返回舊值,然後遞增i。
  • ARM中ADS環境下C語言和彙編語言混合編程及示例
    或者BL指令;  b 在使用物理寄存器時,不要使用過於複雜的C表達式,避免物理寄存器衝突;  c R12和R13可能被編譯器用來存放中間編譯結果,計算表達式值時可能把R0-R3、R12及R14用於子程序調用,因此避免直接使用這些物理寄存器;  d 一般不要直接指定物理寄存器;  e 讓編譯器進行分配內嵌彙編使用的標記是__asm或asm關鍵字,
  • C語言中const關鍵字的妙用總結
    const關鍵字的使用全都掌握了嗎?在編程實踐中你對const的使用是否有困惑呢?今天就給大家一起來探討總結,期望能夠大家解惑並提供參考。C語言中const關鍵字是constant的縮寫,通常翻譯為常量、常數等,有些朋友一看到const關鍵字馬上就想到了常量。事實上在C語言中const功能很強大,它可以修飾變量、數組、指針、函數參數等。
  • 51單片機基礎剖析(基於C語言)
    外部變量的說明與外部變量的定義是不同的,外部變量定義只能有一次,定義的位置在所有函數之外,而同一個程序文件中(不是指模塊文件)的外部變量聲明可以有多次,聲明的置在需要引用該變量的函數之內,外部變量的聲明的作用只是聲明該變量是一個已經在外部定義過了的變量而已。
  • 最全的C語言基礎知識都在這了
    C語言是一門面向過程、抽象化的通用程序設計語言,廣泛應用於底層開發。2、main()----在c語言中稱之為「主函數」,一個c程序有且僅有一個main函數,任何一個c程序總是從main函數開始執行,main函數後面的一對圓括號不能省略。3、被大括號{ }括起來的內容稱為main函數的函數體,這部分內容就是計算機要執行的內容。
  • C語言陷阱與技巧第2節,使用inline函數可以提升程序效率,但是讓...
    打開 Linux 內核原始碼,會發現內核在定義C語言函數時,有很多都帶有 「inline」關鍵字,請看下圖,那麼這個關鍵字有什麼作用呢?inline 關鍵字的作用在C語言程序開發中,inline 一般用於定義函數,inline 函數也被稱作「內聯函數」,C99 和 GNU C 均支持內聯函數。那麼在C語言中,內聯函數和普通函數有什麼不同呢?
  • 單片機c語言教程:C51運算符和表達式
    如果你是個DELPHI 編程愛好者或是DELPHI程式設計師,你對變量的定義也許習慣了DELPHI 的關鍵字,如 int 類型常會用關鍵字Integer來定義,在用 單片機c語言時你還想用回這個的話,你能這樣寫:本文引用地址:http://www.eepw.com.cn/article/170888.htmtypedef int integer;
  • C語言基礎知識學習(一)
    標識符分類a) 關鍵字原先的C89標準中只有32個關鍵字然後在1999年之後進行了兩次技術修正,新出臺了C99標準新增加了5個關鍵字 分別是:restrict, inline, _Complex, _Imaginary, _Bool
  • 計算機二級考試C語言高頻考點
    一,C語言概述C語言基礎知識1.C語言的構成(1)源程序由函數構成,每個函數完成相對獨立的功能(2)每個源程序中必須有且只能有一個主函數可以放在任何位置(5)注釋:括在「/*」與「*/」之間,沒有空格,允許出現在程序的任何位置(6)預處理命令:以「#」開頭的語句2.C程序的生成過程(1)C程序是先由源文件經編譯生成目標文件,然後經過連接生成可執行文件。
  • 深入理解C語言
    我相信你對a的輸出相當有把握,就分別是4,5,6,因為那個靜態變量。對於c呢,你應該也比較肯定,那是一堆亂數。但是你可能不知道b的輸出會是什麼?答案是1,2,3。為什麼和c不一樣呢?因為,如果要初始化,每次調用函數裡,編譯器都要初始化函數棧空間,這太費性能了。但是c的編譯器會初始化靜態變量為0,因為這只是在啟動程序時的動作。
  • C/C+編程筆記:零基礎講解C語言——基本字符集
    C語言過程中最枯燥的部分,分幾次講解,我會儘量用最輕鬆的方式講解 在C語言中,符號常量,變量,數組,函數等都需要一定的名稱,我們把這種名稱成為標識符。也就是說,標識符我們為C語言中出現的所有元素取得名字。
  • 為什麼要加volatile?
    3.變量為什麼要加volatile關鍵字在上面例子中volatile保證代碼指令不會被重排序,首先我們得先了解什麼是volatile關鍵字與及它的特性。volatile關鍵字的特性volatile具有可見性、有序性,不具備原子性。
  • 剖析C語言中a=a+++a的無聊問題
    哈哈,當然了,我還是要對我的師兄弟們負責的,所以我下面的「胡說」中會儘量有理有據。  看法一:  a=a+++++a這個東西可以用來討論,甚至是討論它的無所事處,作為增長知識和發現自身理解問題的漏洞是可以的。但是絕對不能拿來作為考試題目,特別是選擇題或填空題等客觀題目。但是如果作為一道主觀探討題還是挺有趣的,理解深刻的人一定可以寫的很好。
  • C語言基礎:標識符
    標識符:在程式語言中,標識符是用戶編程時使用的名字,變量、常量、函數、語句塊都有名字。是用來標識某個實體的一個符號,是對變量名、函數名、標號和其他各種用戶定義的對象命名。C 標識符是用來標識變量、函數,或任何其他用戶自定義項目的名稱。
  • C語言陷阱與技巧第8節,輸出適當的信息,有利於定位錯誤和異常代碼
    現在編譯這段C語言程序並執行,得到如下結果:# gcc t.c -g# ./a.out cond is true# ./a.out cond is false從輸出結果可以發現,C語言程序輸出了「cond is false」(模擬異常)。