C 語言一文理解 const

C 語言一文理解 const

const在C語言中算是一個比較新的描述符,我們稱之為常量修飾符,就是說,其所修飾的對象為常量。如果想要設法阻止一個變量被改變,那麼可以選擇使用const關鍵字。在為一個變量加上const修飾符的同時,通常需要對它進行初始化,在之後的程序中就不能再去改變它。

可能有的讀者會有疑問,在C語言中不是有預處理指令“#define VariableName VariableValue”可以很方便地進行值替代嗎,為什麼還要引入const修飾符呢?這是因為預處理語句雖然可以很方便地進行值的替代,但是它有個比較致命的缺點,即預處理語句只是進行簡單值替代,缺乏類型檢測機制,這樣,預處理語句就不具備C編譯器嚴格類型檢查的優點,因此它的使用存在著一系列的隱患和侷限性。

在講解const修飾符之前,首先說明const修飾符的幾個典型作用。

❑ const類型定義:指明變量或對象的值是不能被更新的,引入目的是為了取代預編譯指令。

❑ 可以保護被修飾的內容,防止其被意外地修改,增強程序的健壯性。

❑ 編譯器通常不為普通const常量分配存儲空間,而是將它保存在符號表中,這使它成為一個編譯期間的常量,沒有了存儲與讀內存的操作,它的效率也很高。

❑ 可以節省空間,避免不必要的內存分配。

接下來介紹const修飾符的幾種使用方式。

1. const修飾符在函數體內修飾局部變量

const int n=5;

int const n=5;

是等價的。在編程的過程中一定要清楚地知道const修飾的對象是誰,在這裡修飾的是n,和int沒有關係。const 要求它所修飾的對象為常量,不能被改變,同時也不能夠被賦值,所以下面這樣的寫法是錯誤的。

const int n;

n=0;

上面的情況是比較容易理解的,但是當const與指針一起使用時,就容易讓人迷惑。例如,下面是關於p和q的聲明:

 const int *p;
int const *q;

看了上面的代碼,有人可能會覺得“const int *p;”表示的是const int類型的指針(const直接修飾int),而“int const *q;”表示的是int類型的const指針(const直接修飾指針)。實際上,在上面的聲明中, p和q都被聲明為const int類型的指針。而聲明int類型的const指針應該這樣:

int * const r= &n;

以上的p和q都是指向const int類型的指針,也就是說,在以後的程序中不能改變*p的值。而r是一個const指針,在聲明的時候將它初始化為指向變量n(即“r=&n;”)之後, r的值將不允許再改變,但*r的值是可以改變的。在此,為了判斷const的修飾對象,介紹一種常用的方法:以*為界線,如果const位於*的左側,那麼const就是用來修飾指針所指向的變量的,即指針指向常量;如果const位於*的右側,那麼const就是修飾指針本身的,即指針本身是常量。

結合上述兩種const修飾的情況,聲明一個指向const int類型的const指針,如下:

const int * const r=&ss;

這時,既不能修改*r的值,也不能修改r的值。

接下來看const用於修飾常量靜態字符串的情況,例如:

const char* str="fdsafdsa";

如果沒有const的修飾,我們可以在後面寫“str[4]='x'”這樣的語句,這樣會導致對只讀內存區域賦值,然後程序會立刻異常終止。有了const,這個錯誤就能在程序被編譯的時候立即檢查出來,這就是const的好處,讓邏輯錯誤在編譯期被發現。


const int *ptr 和 int const *ptr 例子

C 語言一文理解 const

int main(int argc, char *argv[]) {
\t
\tconst int a = 5; //等價 int const a = 5
\t
\tint i = 100;
\t
\tconst int *iptr = &i; // 等價 int const *iptr = &i;
\t/*
\t 下面這一行是錯誤的代碼
\t *iptr = 200;
\t*/
\tprintf("(1) *iptr = %d, i = %d\\n", *iptr, i);
\ti = 200;
\tprintf("(2) *iptr = %d, i = %d\\n", *iptr, i);
\t
\tint j = 500;
\tiptr = &j;
\t
\tprintf("(3) *iptr = %d, i = %d, j = %d\\n", *iptr, i, j);
\t
\treturn 0;
}

輸出:

(1) *iptr = 100, i = 100
(2) *iptr = 200, i = 200
(3) *iptr = 500, i = 200, j = 500

int * const ptr;

int main(int argc, char *argv[]) {
\t
\tint i = 100;
\tint* const ptr = &i;
\t
\tprintf("(1) *ptr = %d, i = %d\\n", *ptr, i);
\t
\ti = 200;
\tprintf("(2) *ptr = %d, i = %d\\n", *ptr, i);
\t
\t*ptr = 300;
\tprintf("(3) *ptr = %d, i = %d\\n", *ptr, i);
\t

\t/*
\t下面的代碼是錯誤的
\tint j = 400;
\tptr = &j;
\t*/
\treturn 0;
}

編譯輸出:

(1) *ptr = 100, i = 100
(2) *ptr = 200, i = 200
(3) *ptr = 300, i = 300

const int * const ptr

int main(int argc, char *argv[]) {
\t
\tint i = 100;
\tconst int * const ptr = &i;
\t
\tprintf("(1) *ptr = %d, i = %d\\n", *ptr, i);
\t
\ti = 200;
\tprintf("(2) *ptr = %d, i = %d\\n", *ptr, i);
\t
\t/*
\t\t下面這行代碼是錯誤的
\t (*ptr)= 300;
\t */
\t
\t /*
\t 下面的代碼是錯誤的
\t int j = 400;
\t ptr = &j;
\t */
\treturn 0;
}

編譯輸出:

(1) *ptr = 100, i = 100
(2) *ptr = 200, i = 200


分享到:


相關文章: