C語言中關鍵字const、static、volatile的用法分析

1. const
做爲一個程序員,咱們看到關鍵字const時,首先想到的應該是:只讀。由於,它要求其所修飾的對象爲常量,不可對其修改和二次賦值操做(不能做爲左值出現)。看幾個例子:ios

const int a;
	 //同上面的代碼行是等價的,都表示一個常整形數。
	 int const a;
	 
	 /* const具備"左結合"性,即const修飾*,那麼,不難理解,該句表示一個指向整數的常指針,
	    a指向的整數能夠修改,但指針a不能修改。
	 */
	 int *const a;
	 
	 /* 與下面的這一行等價,根據"左結合"性,const修飾的是(*a),也便是一個整數,
	    因此,這兩句表示指針指向一個常整數。
	 */
	 const int *a;
	 int const *a;
	 
	 //根據"左結合"性質,第一個const修飾(*),第二個const修飾(a),所以,這句話表示一個指向常整數的常指針。
	 int const *a const;

合理的使用const關鍵字,不只可以讓編譯器很好的保護相應的數據,還可以直觀的向代碼的閱讀者傳遞有用信息。程序員

2. static
a) static在面向過程編程中的使用場景包括三種:
1) 修飾函數體內的變量(局部)
2) 修飾函數體外的變量(全局)
3) 修飾函數
第一種狀況,static延長了局部變量的生命週期,static的局部變量,並不會隨着函數的執行結束而被銷燬,當它所在 的函數被第再次執行時,該靜態局部變量會保留上次執行結束時的值。如:web

1 #include <stdio.h>
  2 
  3 void test()
  4 {
  5     static int j = 1;
  6     printf("%d\n", j);
  7     j++;
  8 }
  9 int main()
 10 {
 11     test();
 12     test();
 13 
 14     return 0;
 15 }

輸出的結果是:
1
2
對於後面的兩種狀況,static是對它修飾的對象進行了做用域限定,static修飾的函數以及函數外的變量,都是隻能在當前的源文件中被訪問,其它的文件不能直接訪問。當多個模塊中有重名的對象出現時,咱們不妨嘗試用static進行修飾。
b)在面向對象編程中,static能夠被用來修飾類內數據成員和成員函數。
1) 修飾數據成員
*)被static修飾的數據成員實際上至關於類域中的全局變量。所以,對於類的每一個對象來講,它是共有的。它在整個程序中只有一份拷貝,只在定義時分配一次內存,供該類全部的對象使用,其值能夠經過每一個對象來更新。因爲靜態數據成員存儲在全局數據區,所以,在定義時就要分配內存,這也就致使靜態數據成員不能在類聲明中定義。
*)靜態數據成員的初始化舉例: int ClassTest::num = 0;
*)靜態數據成員的訪問舉例: ClassTest ClassInstance; ClassInstance.num 或者 ClassTest::num編程

#include <iostream>

class CTest
{
public:
    CTest() {};
    ~CTest() {};

public:
    static int num;     //聲明
};

int CTest::num = 10;    //定義

int main(void)
{
    CTest obj;
    std::cout << obj.num << std::endl;   //訪問
    std::cout << CTest::num << std::endl;   //訪問
    return 0;
}
2)修飾成員函數
		*)同靜態數據成員同樣,靜態成員函數也是屬於類,而不屬於任何一個類的實體對象,所以,靜態成員函數不含有this指針。同時,它也不能訪問類中其它的非靜態數據成員和函數。(非靜態成員函數能夠訪問靜態數據數據成員和靜態成員函數)
		*)靜態成員函數的訪問方式:  既能夠經過訪問操做符(.)或者(->)來訪問,也能夠經過 <類名> :: <函數名> 的方式訪問。

3. volatile
volatile的做用是告知編譯器,它修飾的變量隨時均可能被改變,所以,編譯後的程序每次在使用該變量的值時,都會從變量的地址中讀取數據,而不是從寄存器中獲取。svg