本文和大家分享的主要是C
語言
volatile
和
const相關內容,一起來看看吧,希望對大家
學習c語言有所幫助。
volatile本意為“易變的”。
在嵌入式環(huán)境中用volatile
關鍵字聲明的變量,在每次對其值進行引用的時候都會從原始地址取值,而不會將值保存在?;蚱渌恢谩?/span>
由于該值“
易變
”
的特性所以,針對其的任何賦值或者獲取值操作都會被執(zhí)行(而不會被優(yōu)化)。由于這個特性,所以該關鍵字在嵌入式編譯環(huán)境中經(jīng)常用來消除
compiler
的優(yōu)化。
舉例說明一些抗優(yōu)化的1.
比如要往某一地址(比如
IO
口寄存器)送兩指令,讓
IO
口進行一次翻轉:
uint8_t *addr =...; //
設備地址
*addr = 1; //
第一個指令
*addr = 2; //
第二個指令
以上程序compiler
可能做優(yōu)化而成:
int *addr = ...;
*addr = 2;
結果第一個指令丟失。如果用volatile, compiler
就不允許做任何的優(yōu)化,從而保證程序的原意,
MCU
庫函數(shù)中對于
IO
寄存器的聲明都會使用
volatile
。
volatile
uint8_t *addr = ...;
*addr = 1;
*addr = 2;
2.
用
volatile
定義的變量會在程序外被改變
,
每次都必須從內存中讀取,而不能重復使用放在寄存器或棧中的備份。
例如:
volatile uint8_t flag;
flag=0;
while(!flag){
doSomeThing();
}
doSomeThingElse();
如果沒有volatile
修飾
flag
則
doSomeThingElse()
可能由于編譯器優(yōu)化不會被執(zhí)行(即使
flag
的值在其他中斷中被更改)。若如上使用了
volatile
,則會每次都會從原始地址取值,這樣當原始地址的值更改后則
while
能中止并繼續(xù)執(zhí)行下方代碼。
3.
很容易得知多任務環(huán)境下各任務間共享的標志也應該加
volatile
。
4.
存儲器映射的硬件寄存器通常也要加
voliate
,因為每次對它的讀寫都可能有不同意義。
例如:
假設要對一個設備進行初始化,此設備的某一個寄存器為0xXXXXXX
。
int *uartSendRegist= (
unsigned
int *)0xXXXXXXXXX;//
定義一個串口數(shù)據(jù)寄存器地址;
int
init(
void){
int i;
for(i=0;i< 10;i++)
{
delaySomeTime();
*uartSendRegist= data
;
}
}
const關鍵字相對而言就簡單了很多,簡單來說主要有以下一些作用:
1.本意為變量 只讀 。
2.大部分單片機的compiler會把中const修飾的全局變量存放在MCU的ROM中.把一些很大的不變數(shù)據(jù)申明為const。
3.使編譯器很自然地保護那些不希望被改變的參數(shù),防止其被無意的代碼修改。
順便說一個問題,一個參數(shù)既可以是const還可以是volatile嗎?
這是可以的,因為const的意思是只讀,而不是不變。最簡單的例子比如只讀的狀態(tài)寄存器。
來源:網(wǎng)絡