深入聊一下const關鍵字

2022-09-20 13:06:12 字數 4251 閱讀 9418

const是乙個c語言的關鍵字,它限定乙個變數不允許被改變。使用const在一定程式上可以提高程式的健壯性,另外,在**別人**的時候,清晰理解const所起的作用,對理解別人的程式有所幫助。

下面簡單描述一下const,基本都是教科書的知識。const修飾的變數,其值存放在唯讀資料段中,其值不能被改變。稱為唯讀變數。關於什麼是資料段,什麼是**段,請看我之前的文章《c語言的記憶體分配》。

int

const

a;const

int a;

上面兩條語句都可以將a宣告為乙個整數,它的值不能被修改。這兩種方式你可以任意選一種即可。

常量在定義時可以被初始化。

int

const a =15;

當指標和常量結合時,就會很有趣,因為有兩樣東西都可能成為常量,指標和它指向的實體。一般大家在大學考計算機二級和面試時經常會遇到的。

int *a;
a就是乙個很普通的指向整型的指標。

int

const *a;

這時則是乙個指向整型常量的指標。也就是說,你可以修改指標的值,但是不能修改它指向的值。

int *const a;
這時a是乙個指向整型的常量指標。這個指標是常量,它的值無法修改,但是你可以修改它所指向的整型的值。

int

const *const a;

這個時候無論是指標本身還是它所指向的值都是常量,都不允許修改。

那麼問題來了,就像c語言的運算子的優先順序,這個東西很不好記憶,在實際開發中,我們直接多用()符號解決優先順序的問題。上面指標和const結合那麼麻煩,學習為了什麼呢?

1、合理地使用關鍵字const可以使編譯器很自然地保護那些不希望被改變的引數,防止其被無意的**修改。簡而言之,這樣可以減少bug的出現

2、正是基於上面的原因,一些優秀的開源**都會利用const這個屬性,深入理解後,方便我們閱讀理解一些優秀的開源**

上文就簡述了一下教科書中的const定義,現在說一下const在我日常開發中的應用。

在微控制器開發中

const定義乙個常量,在微控制器開發中,乙個定義在函式體外的常量constint a = 5; 它是儲存在微控制器內部flash裡的,不懂的同學請看之前的文章《c語言在stm32中的記憶體分配》。那麼上文提到和指標結合時,也是儲存在內部flash中嗎?我們來驗證一下

int data = 0x1234

;int

const *a = &data;

int *const b= &data;

intconst *const c= &data;

int main(void

)

它們的記憶體分配如下

b和c是分配到內部flash的,a是分配到ram中的。其實這也很好理解,根據上面的const的定義,微控制器在分配時,將不能修改的變數,也就是唯讀變數放到flash中,可以讀寫的變數放到ram中,這個大家仔細想一下就明白了。

常量作為函式的引數

非指標引數(也就是傳值引數)不會被修改原始值,const對它是沒有意義的,所以這裡只討論引數是指標加const的情況。

在上面看到,指標加const共3種情況,這裡先討論int const *a; 也就是你可以修改指標的值,但是不能修改它指向的值。

int fun(int *p) 

else

}

上面是個簡單的例子,也就是傳入乙個指標,函式讀取指標指向的內容,執行不同的命令。類似串列埠接收,乙個函式內部處理這些資料,但是不能修改,可能串列埠接收的資料在其他地方還有用。

在上述例子中,沒有問題的,因為**全在「掌控」中。函式內部是否進行寫操作,自己是知道的。但還有乙個更規範的寫法。

int fun(int

const *p)

else

}

這裡寫法,就是明顯表現出自己的設計意圖,函式內部不可以對指標指向的內容進行修改,只能讀取。

如果嘗試修改,編譯器會直接報錯的。但是函式內部也是可以繞過去,修改的資料的,如下

int fun(const

int *p)

那麼對於int *const a;有沒有對應的使用場景呢?如下

這樣的介面設計,如果函式內部嘗試修改指標的值,也就是指標指向的位置,編譯器就會直接報錯。

不過這裡例子很現實,因為即使去掉p2的const修飾,編譯器會直接報waring,因為p2是入參。這裡只是簡單舉例子,大家理解意思就好。

在日常開發中,入參是intconst *a;使用場景比較多。

c++中應用加const

c++中可以使用應用的語法,這裡不再展開什麼是應用,如下例子,c++函式引數中引用時也常加const修飾,如下

void find(constint  &x)

最後,舉兩個常用的標準c庫函式宣告,它們都是使用const的典範。

1.字串拷貝函式:char*strcpy(char*strdest,constchar *strsrc);

2.返回字串長度函式:intstrlen(constchar *str);

#define預編譯和const在某些情況下有些「混淆」,如下

#define max_num 5

intconst max_num = 5

;void

fun()

上述**5行和6行都能起效果。那麼我們就詳細分析一下它們的區別

1#define的資料是巨集定義,它占用的是**段空間(微控制器對應:內部flash),const定義乙個資料型別,它占用的是data段(微控制器對應:內部ram)。

2如上,#define是巨集定義,在預編譯階段直接替換,而const是資料型別。

#define max_num 5

intconst max_num = 5

;int

data[max_num];

intdata2[max_num];

上述**第4行是編譯不過的,因為max_num是乙個int的資料型別變數,陣列定義的長度不能用變數。實際上,在更章節第乙個例子,只用於判斷長度,#define更加合適,因為只要允許使用字面值常量的地方都可以使用巨集定義

3define只是簡單的字串替換,沒有型別檢查。而const有對應的資料型別,是要進行判斷的,可以避免一些低階的錯誤。define只是簡單的字串替換會導致邊界效應,

比如定義

#define a 1

#define b a+3

#define c a/b3

那麼c是多少呢?c=a/b3=a/a+33=1/1+33=10;所以這種用的時候可以直接都用個括號括起來,就不怕邊界效應了。

4const不能重定義,不可以定義兩個一樣的,而define就比較牛氣了,它通過undef取消某個符號的定義,再重新定義。並還可以用於判斷巨集定義是否存在,常用於標頭檔案防止標頭檔案被重複引用。 

#ifndef graphics_h //

防止graphics.h被重複引用

#definegraphics_h

……**……

#endif

5const常量可以進行除錯的,define是不能進行除錯的,主要是預編譯階段就已經替換掉了,除錯的時候就沒它了。

聊一聊關鍵字 this

this可能是最靈活也是用的最多的關鍵字,它的作用如下 表示類中的屬性,方法 呼叫本類中的構造方法 表示當前物件 下面具體來說一說各個作用的用處 現在有這樣乙個類 class person public string getinfo 從構造方法的兩個傳遞引數的名稱很難看出n和a到底代表什麼,所以我們...

簡單聊一下const

聯絡 define 不分配記憶體,給出的是立即數,只是簡單的替換。有多少次使用就進行多少次拷貝替換,在記憶體中會有多個拷貝,消耗記憶體大 const 在靜態儲存區中分配空間,在程式執行過程中記憶體中只有乙個拷貝 更多的戳這裡和那裡 這裡 那裡const m 10 m 的值不能在程式中被修改 但可以通...

(一)const關鍵字

一 對於 const 關鍵字我在這裡說一下在 c 語言中的使用 第乙個需要理解的是const修飾的是變數 修飾變數的目的是為了使得該變數唯讀 二 為什麼要使用 const 關鍵字 方便 閱讀,清楚的告訴其他人程式哪些變數是不可以被修改的 同時也可以方便自己 的書寫,因為寫的 量過大,一些變數你不希望...