在C語言中static關鍵字有如下的做用程序員
1,能夠用來修飾局部變量。局部變量在函數內部定義的,只有在函數內部有效(做用域),其缺省的存儲方式是動態存儲的,即指令執行到變量定義處時纔給變量分配存儲單元,函數執行結束後變量的內存單元就會被釋放掉(生命週期)。用static聲明局部變量時,則會改變變量的存儲方式,使變量成爲靜態局部變量,即在編譯時就爲變量分配內存,直到程序運行結束退出才釋放內存單元。若是在子函數中的變量,若是想要這個變量在函數執行結束後不被釋放掉,可使用static修飾。緩存
2,static修飾全局變量的時候,這個全局變量只能在本文件中訪問,不能在其它文件中訪問,即使是extern外部聲明也不能夠。函數
3,static修飾一個函數,則對函數的鏈接方式產生影響,這個函數的只能在本文件中調用,不能被其餘文件調用。這個有點相似於C#中的private。使用靜態函數的好處是,不用擔憂與其餘文件的同名函數產生干擾,另外對函數自己也是一種保護機制。性能
const關鍵字用來定義常量,被它修飾的變量值不能再改變。優化
const在修飾變量的時候必定要初始化,不然以後就不能再進行賦值了。3d
1,常量指針不能經過這個指針改變變量的值,可是能夠經過其餘的引用來改變變量的值。指針
/* xutopia */ #include "stdio.h" int main() { int x = 6; const int *p; p = &x; printf("x=%d\r\n", x); printf("*p=%d\r\n", *p); x = 8; printf("\r\nx=%d\r\n", x); printf("*p=%d\r\n", *p); system("pause"); }
運行結果以下code
2,常量指針指向的值不能經過這個指針改變,可是常量指針能夠指向其餘的地址。blog
/* xutopia */ #include "stdio.h" int main() { int x = 6; int y = 8; const int *p; p = &x; printf("x=%d,y=%d\r\n", x, y); printf("*p=%d\r\n", *p); p = &y; printf("*p=%d\r\n", *p); system("pause"); }
3,指針常量是指針自己是一個常量不能夠再指向其餘地址排序
/* xutopia */ #include "stdio.h" int main() { int x = 6; int y = 8; int *const p=&x;//指針常量 printf("x=%d,y=%d\r\n", x, y); printf("*p=%d\r\n", *p); system("pause"); }
區分常量指針和指針常量的關鍵就在於 * 的位置。爲了方便記憶,把 * 讀做「指針」,把const讀做常量:
int const * x:常量指針;
int *const x:指針常量。
4,指向常量的常量指針,這種指針指向的位置不能改變,指向的值也不能改變,可是依然能夠經過其餘應用來改變。
/* xutopia */ #include "stdio.h" int main() { int x = 6; int y = 8; const int* const p = &x; printf("x=%d,y=%d\r\n", x, y); printf("*p=%d\r\n", *p); //*p = 9;//err //p = &y;//err x = 9; printf("*p=%d\r\n", *p); system("pause"); }
參數參數也能夠用const來修飾,防止函數修改參數中的內容,具體特性如上訴所介紹,常量指針,指針常量,常量指針常量。函數的返回值也能夠用const來修飾,不過意義不是很大。
/* xutopia */ #include "stdio.h" const int* fun1(int param1, int* param2, const int param3, const int* param4, int *const param5,const int *const param6) { printf("param1=%d\r\n", param1); printf("*param2=%d\r\n", *param2); printf("param3=%d\r\n", param3); printf("*param4=%d\r\n", *param4); printf("*param5=%d\r\n", *param5); printf("*param6=%d\r\n", *param6); param1 = 16; printf("param1=%d\r\n", param1); *param2 = 13; //param3 = 14;//err param4 = ¶m1; printf("param4=%d\r\n", *param4); //*param4 = 14;//err *param5 = 15; printf("param5=%d\r\n", *param5); //param5 = ¶m1;//err //param6 = ¶m1;//err //*param6 = 1;//err return param5; } int main() { int a = 11, b = 12; int* p1, *p2; const int *re1; int *re2; p1 = &a; p2 = &b; re1 = fun1(1, p1, 3, p2, p2, p2); //re2 = fun1(1, p1, 3, p2,p2,p2);//right printf("\r\n*p1=%d\r\n", *p1); printf("*p2=%d\r\n", *p2); //printf("*re=%d\r\n", *re2); printf("*re=%d\r\n", *re1); system("pause"); }
全局變量的做用域是整個文件,若是用在其餘文件中用external聲明,那麼全局變量能夠做用到其餘的文件夾,爲了防止全局變量在使用的過程當中被不經意的修改,能夠用const修飾,這樣就能夠防止沒必要要的修改。
volatile關鍵字提醒編譯器它所定義的變量隨時均可能改變,所以編譯後的程序每次須要存儲和讀取這個變量的時候,都對直接從這個地址中讀取數據。
若是沒有volatile關鍵字,則編譯器可能優化存儲和讀取,若是這個變量由別的程序更新的話,將出現不一致的現象。若是用這個關鍵字聲明變量,編譯器對訪問該變量的代碼就再也不進行優化,從而能夠穩定地訪問特殊的地址。
簡而言之,volatile聲明的變量,就是要求程序運行的時候,每次從這個變量的地址讀取。
編譯器優化介紹:因爲內存訪問速度遠不及CPU處理速度,爲提升機器總體性能,在硬件上引入硬件高速緩存Cache(例如STM32某些型號就支持cache),加速對內存的訪問。另外在現代CPU中指令的執行並不必定嚴格按照順序執行,沒有相關性的指令能夠亂序執行,以充分利用CPU的指令流水線,提升執行速度。以上是硬件級別的優化。再看軟件一級的優化:一種是在編寫代碼時由程序員優化,另外一種是由編譯器進行優化。編譯器優化經常使用的方法有:將內存變量緩存到寄存器;調整指令順序充分利用CPU指令流水線,常見的是從新排序讀寫指令。對常規內存進行優化的時候,這些優化是透明的,並且效率很好。由編譯器優化或者硬件從新排序引發的問題的解決辦法是在從硬件(或者其餘處理器)的角度看必須以特定順序執行的操做之間設置內存屏障(memory barrier),Linux 提供了一個宏解決編譯器的執行順序問題。void Barrier(void)這個函數通知編譯器插入一個內存屏障,但對硬件無效,編譯後的代碼會把當前CPU寄存器中的全部修改過的數值存入內存,須要這些數據的時候再從新從內存中讀出。