天天看點

restrict和volatile

restrict

允許編譯器優化某部分代碼以更好地支援計算,它隻能用于指針,表明該指針是通路資料對象的唯一且初始的方式。

用于告訴編譯器,對象已經被指針所引用,不能通過除該指針外所有其他直接或間接的方式修改該對象的内容。

#include<stdio.h>
int main()
{
	int arr[10];
	int *restrict restar=(int *)malloc(10*sizeof(int));
	int *par=ar;
	for(int n=0;n<10;n++)
	{
		par[n]+=5;
		restar[n]+=5;
		arr[n]*=2;
		par[n]+=3;
		restar[n]+=3;	 
	}
}
           

因為restar是通路它所指向的資料塊的唯一且初始的方式,編譯器可以把涉及restart的兩條語句替換成下面這條語句,效果相同 

                restar[n]+=8;

但是把與par相關的兩條語句替換成下面的語句,将導緻計算錯誤

                par[n]+=8;

因為for循環在par兩次通路相同的資料之間,用ar改變了該資料的值.在該例中,如果使用了 restrict 關鍵字,編譯器就可以選擇捷徑優化計算 

restrict還可用于函數形參中的指針,這意味着編譯器可以假定在函數體内其他

辨別符不會修改該指針指向的資料,而且編譯器可以嘗試對其優化,使其不做别的用途

volatile 類型限定符

告知計算機,代理可以改變該變量的值,通常,它被用于硬體位址及 在其他程式或同時運作的線程中共享資料,例如,一個位址上可能存儲着目前的時鐘時間,無論程式做什麼,位址上的值都随着時間的變化而改變,或者一個位址用于接受另一台計算機傳入的資訊.簡單地說就是防止編譯器對代碼進行優化。 確定本條指令不會因編譯器的優化而省略,且要求每次直接讀值.精确地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用儲存在寄存器裡的備份。 
volatile int locl; 	//易變型變量,locl 是一個易變的位置說明這變量可能會被意想不到的改變,這樣,編譯器就不會假設這個變量的值了 
volatile int *ploc;		//指向易變型變量的指針,

val1=x;
val2=x;
智能的(進行優化的)編譯器會注意到以上代碼使用了兩次x,但并未改變它的值,于是編譯器
把x的值臨時存儲在寄存器中,然後在val2需要使用x時,才從寄存器中(而不是從原始記憶體位置
上)讀取x的值,以節約時間,這個過程被稱為高速緩存。
	但是如果一些其他代理在以上兩句語句之間改變了x的值,就不能這樣優化了,如果沒有
volatile 關鍵字,編譯器就不會知道這種事情是否會發生。而現在,如果未使用volatile 關鍵字,編譯
器會假定變量的值在使用過程中不變,然後嘗試優化 

volatile const int loc;		//程式不能改變的變量,但是可以通過代理改變 
const volatile int *ploc;