商務英語計算機英語

c語言const的用法

本文已影響 2.26W人 

const是一個C語言的關鍵字,它限定一個變數不允許被改變。使用const在一定程度上可以提高程式的安全性和可靠性,另外,在觀看別人程式碼的時候,清晰理解const所起的作用,對理解對方的程式也有一些幫助。下面小編就跟大家介紹下c語言const的用法。

ing-bottom: 100%;">c語言const的用法

我們來分情況看語法上它該如何被使用。

1、函式體內修飾區域性變數。

例:

void func()

{

const int a=0;

}

首先,我們先把const這個單詞忽略不看,那麼a是一個int型別的區域性自動變數,我們給它賦予初始值0。然後再看const.

const作為一個型別限定詞,和int有相同的地位。

const int a;

int const a;

是等價的。於是此處我們一定要清晰的明白,const修飾的物件是誰,是a,和int沒有關係。const 要求他所修飾的物件為常量,不可被改變,不可被賦值,不可作為左值(l-value)。

這樣的寫法也是錯誤的。

const int a;

a=0;

這是一個很常見的使用方式:

const double pi=3.14;

在程式的後面如果企圖對pi再次賦值或者修改就會出錯。

然後看一個稍微複雜的例子。

const int* p;

還是先去掉const 修飾符號。

注意,下面兩個是等價的。

int* p;

int *p;

其實我們想要說的是,*p是int型別。那麼顯然,p就是指向int的指標。

同理

const int* p;

其實等價於

const int (*p);

int const (*p);

即,*p是常量。也就是說,p指向的資料是常量。

於是

p+=8; //合法

*p=3; //非法,p指向的資料是常量。

那麼如何宣告一個自身是常量指標呢?方法是讓const儘可能的靠近p;

int* const p;

const右面只有p,顯然,它修飾的是p,說明p不可被更改。然後把const去掉,可以看出p是一個指向 int形式變數的指標。

於是

p+=8; //非法

*p=3; //合法

再看一個更復雜的例子,它是上面二者的綜合

const int* const p;

說明p自己是常量,且p指向的變數也是常量。

於是

p+=8; //非法

*p=3; //非法

const 還有一個作用就是用於修飾常量靜態字串。

例如:

const char* name="David";

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

const 還可以用來修飾陣列

const char s[]="David";

與上面有類似的作用。

2、在函式宣告時修飾引數

來看實際中的一個例子。

NAME

memmove -- copy byte string

LIBRARY

Standard C Library (libc, -lc)

SYNOPSIS

#include <string.h>

void *

memmove(void *dst, const void *src, size_t len);

這是標準庫中的一個函式,用於按位元組方式複製字串(記憶體)。它的第一個引數,是將字串複製到哪裡去(dest),是目的地,這段記憶體區域必須是可寫。它的第二個引數,是要將什麼樣的字串複製出去,我們對這段記憶體區域只做讀取,不寫。於是,我們站在這個函式自己的角度來看,src 這個指標,它所指向的記憶體內所存

儲的資料在整個函式執行的過程中是不變。於是src所指向的內容是常量。於是就需要用const修飾。例如,我們這裡這樣使用它。

const char* s="hello";

char buf[100];

memmove(buf,s,6); //這裡其實應該用strcpy或memcpy更好

如果我們反過來寫,

memmove(s,buf,6);

那麼編譯器一定會報錯。事實是我們經常會把各種函式的引數順序寫反。事實是編譯器在此時幫了我們大忙。如果編譯器靜悄悄的不報錯,(在函式宣告處去掉const即可),那麼這個程式在執行的時候一定會崩潰。

這裡還要說明的一點是在函式引數宣告中const一般用來宣告指標而不是變數本身。

例如,上面的size_t len,在函式實現的時候可以完全不用更改len的值,那麼是否應該把len也宣告為常量呢?可以,可以這麼做。我們來分析這麼做有什麼優劣。

如果加了const,那麼對於這個函式的實現者,可以防止他在實現這個函式的時候修改不需要修改的值(len),這樣很好。

但是對於這個函式的使用者,

1。這個修飾符號毫無意義,我們可以傳遞一個常量整數或者一個非常量整數過去,反正對方獲得的只是我們傳遞的一個copy。

2。暴露了實現。我不需要知道你在實現這個函式的時候是否修改過len的值。

所以,const一般只用來修飾指標。

再看一個複雜的例子

int execv(const char *path, char *const argv[]);

著重看後面這個,argv.它代表什麼。

如果去掉const,我們可以看出

char * argv[];

argv是一個數組,它的每個元素都是char *型別的指標。

如果加上const.那麼const修飾的是誰呢?他修飾的是一個數組,argv[],意思就是說這個陣列的元素是隻讀的。那麼陣列的元素的是什麼型別呢?是char *型別的指標.也就是說指標是常量,而它指向的資料不是。

於是

argv[1]=NULL; //非法

argv[0][0]='a'; //合法

3、全域性變數。

我們的原則依然是,儘可能少的使用全域性變數。我們的第二條規則 則是,儘可能多的使用const。如果一個全域性變數只在本檔案中使用,那麼用法和前面所說的函式區域性變數沒有什麼區別。如果它要在多個檔案間共享,那麼就牽扯到一個儲存型別的問題。

有兩種方式。

1.使用extern

例如

extern const double pi;

const double pi=3.14;

然後其他需要使用pi這個變數的,包含file1.h

#include "file1.h"

或者,自己把那句聲明覆制一遍就好。

這樣做的結果是,整個程式連結完後,所有需要使用pi這個變數的共享一個儲存區域。

2.使用static,靜態外部儲存類

static const pi=3.14;

需要使用這個變數的*.c檔案中,必須包含這個標頭檔案。

前面的static一定不能少。否則連結的時候會報告說該變數被多次定義。這樣做的結果是,每個包含了constant.h的*.c檔案,都有一份該變數自己的copy,該變數實際上還是被定義了多次,佔用了多個儲存空間,不過在加了static關鍵字後,解決了檔案間重定義的衝突。壞處是浪費了儲存空間,導致連結完後的可執行檔案變大。但是通常,這個,小小几位元組的變化,不是問題。好處是,你不用關心這個變數是在哪個檔案中被初始化的。

最後,說說const的作用。

const 的好處,是引入了常量的概念,讓我們不要去修改不該修改的記憶體。直接的作用就是讓更多的邏輯錯誤在編譯期被發現。所以我們要儘可能的多使用const。但是很多人並不習慣使用它,更有甚者,是在整個程式 編寫/除錯 完後才補const。如果是給函式的宣告補const,尚好。如果是給 全域性/區域性變數補const,那麼……那麼,為時已晚,無非是讓程式碼看起來更漂亮了。

猜你喜歡

熱點閱讀

最新文章

推薦閱讀