中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
C語言的那些小秘密之const修飾符

C語言的那些小秘密之const修飾符

分類: 【C語言的那些小秘密】 265人閱讀 評(píng)論(2) 收藏 舉報(bào)
或許還有不少人對(duì)于const符理解的并不深刻,都只是停留在一個(gè)比較淺的層面上,僅僅是在讀別人代碼的時(shí)候看到了const修飾符的使用,自己的寫代碼的過中從未使用過,所以自然對(duì)于const符比較陌生。那么到底什么是const符,我們?cè)谧约壕帉慍語言代碼的過程中又該如何有效的使用const符呢,現(xiàn)在讓我們來學(xué)習(xí)下const符的使用。

const在C語言中算是一個(gè)比較新的描述符,我們稱之為常量修飾符,即就是說其所修飾的對(duì)象為常量。當(dāng)你代碼中想要設(shè)法阻止一個(gè)變量被改變,那么這個(gè)時(shí)候可以選擇使用const關(guān)鍵字。在你給一個(gè)變量加上const修飾符的同時(shí),通常需要對(duì)它進(jìn)行初始化,在之后的程序中就不能再去改變它。

可能有的人會(huì)有一個(gè)疑問,我們不是有在C中有預(yù)處理指令#define VariableName VariableValue 可以很方便地進(jìn)行值替代,干嘛還要引入const修飾符呢?!這是因?yàn)轭A(yù)處理語句雖然可以很方便的進(jìn)行值得替代,但它有個(gè)比較致命的缺點(diǎn),即預(yù)處理語句僅僅只是簡(jiǎn)單值替代,缺乏類型的檢測(cè)機(jī)制。這樣預(yù)處理語句就不能享受C編譯器嚴(yán)格類型檢查的好處,正是由于這樣,使得它的使用存在著一系列的隱患和局限性。

在講解const修飾符之前,我們?cè)诖耸紫冉o出const修飾符的幾個(gè)典型作用:

1.   const類型定義:指明變量或?qū)ο蟮闹凳遣荒鼙桓?引入目的是為了取代預(yù)編譯指令

2.   可以保護(hù)被修飾的東西,防止意外的修改,增強(qiáng)程序的健壯性;

3.   編譯器通常不為普通const常量分配存儲(chǔ)空間,而是將它們保存在符號(hào)表中,這使得它成為一個(gè)編譯期間的常量,沒有了存儲(chǔ)與讀內(nèi)存的操作,使得它的效率也很高。

4.    可以節(jié)省空間,避免不必要的內(nèi)存分配。

 接下來看看具體的使用。

一、const修飾符在函數(shù)體內(nèi)修飾局部變量。

 const int n=5;

 int const n=5;

是等價(jià)的。我們?cè)诰幊痰倪^程中一定要清楚的知道const修飾的對(duì)象是誰,在這里修飾的是n,和int沒有關(guān)系。const 要求他所修飾的對(duì)象為常量,不能被改變,同時(shí)也不能夠被賦值,所以下面這樣的寫法是錯(cuò)誤的。
const int n;
n=0;

對(duì)于上面的情況是比較容易理解的,但是當(dāng)const與指針一起使用時(shí),就容易讓人感到迷惑。例如,下面我們來看看一個(gè)p和q的聲明:

 const int *p;
 int const *q;

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

 int * const r= &n;

以上的p和q都是指向const int類型的指針,也就是說,你在以后的程序里不能改變*p的值。而r是一個(gè)const指針,它在聲明的時(shí)候被初始化指向變量n(即r=&n;)之后,r的值將不再允許被改變,但*r的值可以改變。在此對(duì)于判斷const的修飾對(duì)象給出一種常使用的方法,我們以*為界線,如果const位于*的左側(cè),則const就是用來修飾指針?biāo)赶虻淖兞?,即指針指向?yàn)槌A浚蝗绻鹀onst位于*的右側(cè),const就是修飾指針本身,即指針本身是常量。

還是給個(gè)代碼來加深下大家的印象吧。

#include <stdio.h>

int main(int argc, char* argv[])
{
 int ss=9;
 int * const r= &ss;
 printf("%d\n",*r);
 printf("%d\n",ss);
 *r=100;
 printf("%d\n",*r);
 printf("%d\n",ss);

    return 0;
}

運(yùn)行結(jié)果如下:

簡(jiǎn)單的來分析下吧,因?yàn)閞指向的是ss的地址,所以修改r指向的地址單元的值的同時(shí)ss的值也隨之變化。

結(jié)合上述兩種const修飾的情況,我們現(xiàn)在應(yīng)該可以完成如何聲明一個(gè)指向const int類型的const指針,如下:

const int * const r=&ss;

這個(gè)時(shí)候我們既不能修改*r的值也不能修改r的值。

接下來看看const用于修飾常量靜態(tài)字符串,例如:例如:

const char* str="fdsafdsa";

如果沒有const的修飾,我們可能會(huì)在后面有意無意的寫str[4]='x'這樣的語句,這樣會(huì)導(dǎo)致對(duì)只讀內(nèi)存區(qū)域的賦值,然后程序會(huì)立刻異常終止。有了const,這個(gè)錯(cuò)誤就能在程序被編譯的時(shí)候就立即檢查出來,這就是const的好處。讓邏輯錯(cuò)誤在編譯期被發(fā)現(xiàn)。

二、const在函數(shù)聲明時(shí)修飾參數(shù)

void *memmove( void* dest, const void* src, size_t count ); 這是標(biāo)準(zhǔn)庫中的一個(gè)函數(shù),在頭文件#include <string.h>中聲明,其功能為由src所指內(nèi)存區(qū)域復(fù)制count個(gè)字節(jié)到dest所指內(nèi)存區(qū)域。用于按字節(jié)方式復(fù)制字符串(內(nèi)存)。它的第一個(gè)參數(shù),是將字符串復(fù)制到哪里去(dst),是目的地,這段內(nèi)存區(qū)域必須是可寫。它的第二個(gè)參數(shù),是要將什么樣的字符串復(fù)制出去,我們對(duì)這段內(nèi)存區(qū)域只做讀取,不寫。于是,我們站在這個(gè)函數(shù)自己的角度來看,src 這個(gè)指針,它所指向的內(nèi)存內(nèi)所存儲(chǔ)的數(shù)據(jù)在整個(gè)函數(shù)執(zhí)行的過程中是不變。于是src所指向的內(nèi)容是常量。于是就需要用const修飾。另外需要強(qiáng)調(diào)的一點(diǎn)就是src和dest所指內(nèi)存區(qū)域可以重疊,但復(fù)制后dest內(nèi)容會(huì)被更改。函數(shù)返回指向dest的指針。

例如,我們這里這樣使用它。

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
 const char* str="hello";
 char buf[10];
 memmove(buf,str,6);
 printf("%s\n",buf);

    return 0;
}

運(yùn)行結(jié)果如下:

如果我們反過來寫,memmove(str,buf,6);那么編譯器一定會(huì)報(bào)錯(cuò)。事實(shí)是我們經(jīng)常會(huì)把各種函數(shù)的參數(shù)順序?qū)懛?。事?shí)是編譯器在此時(shí)幫了我們大忙。如果編譯器靜悄悄的不報(bào)錯(cuò),即在函數(shù)聲明void *memmove( void* dest, const void* src, size_t count ); 處去掉const即可,那么這個(gè)程序在運(yùn)行的時(shí)候一定會(huì)崩潰。這里還要說明的一點(diǎn)是在函數(shù)參數(shù)聲明中const一般用來聲明指針而不是變量本身。例如,上面的size_t len,在函數(shù)實(shí)現(xiàn)的時(shí)候可以完全不用更改len的值,那么是否應(yīng)該把len也聲明為常量呢?可以,可以這么做。我們來分析這么做有什么優(yōu)劣。如果加了const,那么對(duì)于這個(gè)函數(shù)的實(shí)現(xiàn)者,可以防止他在實(shí)現(xiàn)這個(gè)函數(shù)的時(shí)候修改不需要修改的值(len),這樣很好。但是對(duì)于這個(gè)函數(shù)的使用者,

1.飾符號(hào)毫無意義,我們可以傳遞一個(gè)常量整數(shù)或者一個(gè)非常量整數(shù)過去,反正對(duì)方獲得的只是我們傳遞的一個(gè)copy。
2實(shí)現(xiàn)。我不需要知道你在實(shí)現(xiàn)這個(gè)函數(shù)的時(shí)候是否修改過len的值。

所以,const一般只用來修飾指針。再看一個(gè)復(fù)雜的例子
int execv(const char *path, char *const argv[]);
著重看后面這個(gè),argv.它代表什么。如果去掉const,我們可以看出char * argv[],argv是一個(gè)數(shù)組,它的每個(gè)元素都是char *類型的指針。如果加上const.那么const修飾的是誰呢?修飾的是一個(gè)數(shù)組,argv[]意思就是說這個(gè)數(shù)組的元素是只讀的。那么數(shù)組的元素的是什么類型呢?是char *類型的指
針.也就是說指針是常量,而它指向的數(shù)據(jù)不是。于是
argv[1]=NULL; //非法
argv[0][0]='a'; //合法

三、const作為全局變量

在程序中,我們要盡可能少的使用全局變量。因?yàn)槠渥饔糜蚴侨?,所以程序范圍?nèi)都可以修改它的值,從而導(dǎo)致了全局變量不能保證值的正確性,如果出現(xiàn)錯(cuò)誤非常難以發(fā)現(xiàn)。如果在多線程中使用全局變量,你的程序?qū)?huì)錯(cuò)的一塌糊涂。多線程會(huì)修改另一個(gè)線程使用的全局變量的值,如果不注意,一旦出錯(cuò)后果不堪設(shè)想。所以在這種情況下萬不得意不要使用全局變量。我們要盡可能多的使用const。如果一個(gè)全局變量只在本文件中使用,那么用法和前面所說的函數(shù)局部變量沒有什么區(qū)別。如果它要在多個(gè)文件間共享,那么就牽扯到一個(gè)存儲(chǔ)類型的問題。

有兩種方式。

1.用extern
例如
/* pi.h */
extern const double pi;
/* pi.c */
const double pi=3.14;
然后其他需要使用pi這個(gè)變量的,包含pi.h

#include pi.h

或者,自己把那句聲明復(fù)制一遍就好。這樣做的結(jié)果是,整個(gè)程序鏈接完后,所有需要使用pi這個(gè)變量的共享一個(gè)存儲(chǔ)區(qū)域。

2.使用static,靜態(tài)外部存儲(chǔ)類

/* constant.h */
static const double pi=3.14;
需要使用這個(gè)變量的*.c文件中,必須包含這個(gè)頭文件。前面的static一定不能少。否則鏈接的時(shí)候會(huì)報(bào)告說該變量被多次定義。這樣做的結(jié)果是,每個(gè)包含了constant.h的*.c文件,都有一份該變量自己的copy,該變量實(shí)際上還是被定義了多次,占用了多個(gè)存儲(chǔ)空間,不過在加了static關(guān)鍵字后,解決了文件間重定義的沖突。壞處是浪費(fèi)了存儲(chǔ)空間,導(dǎo)致鏈接完后的可執(zhí)行文件變大。通常來說,對(duì)于存儲(chǔ)空間字節(jié)的變化不是太大的情況下,不是問題。好處是,你不用關(guān)心這個(gè)變量是在哪個(gè)文件中被初始化的。

下面再來看看一段代碼:

#include <stdio.h>

int main()
{
 const int a=12;
 const int *p=&a;           // 這個(gè)是指向常量的指針,指針指向一個(gè)常量
 p++;                               //可以指針可以自加、自減
 p--;                                  //合法


 int const *q=&a;           // 這個(gè)和上面const int *p=&a;是一個(gè)意思
 int b=12;


 int * const r=&b;           //這個(gè)就是常量指針(常指針),不能自加、自減,并且要初始化
 //r++;                               //編譯出錯(cuò) 


 const int * const t=&b; //這個(gè)就是指向常量的常指針,并且要初始化,用變量初始化


 //t++;                                //編譯出錯(cuò)
 p=&b;                              //const指針可以指向const和非const對(duì)象
 q=&b;                              //合法

 return 0;
}

為了便于代碼的閱讀理解,在此就直接在代碼后面加注釋,就不在這兒做過多的講解了。

綜上所述,const 的好處,是引入了常量的概念,讓我們不要去修改不該修改的內(nèi)存。直接的作用就是讓更多的邏輯錯(cuò)誤在編譯期被發(fā)現(xiàn)。所以我們要盡可能的多使用const。以上內(nèi)容難免有錯(cuò),如果錯(cuò)誤,請(qǐng)糾正!如需轉(zhuǎn)載,請(qǐng)注明出處!

在此說幾句閑話,前幾天無意間在google搜索時(shí)發(fā)現(xiàn)有個(gè)別網(wǎng)站和個(gè)人未經(jīng)我的同意就私自在不標(biāo)注任何出處信息的情況下轉(zhuǎn)載我的文章,有個(gè)網(wǎng)友更是以第一作者的身份在另外一個(gè)論壇進(jìn)行發(fā)表,沒有標(biāo)注任何文章出處的相關(guān)信息。我希望在轉(zhuǎn)載文章的同時(shí)也能標(biāo)注下出處,畢竟也算是對(duì)原創(chuàng)起碼的一點(diǎn)尊重,希望我們大家都有一種尊重原創(chuàng)的意識(shí),我的博客地址:http://blog.csdn.net/bigloomy

分享到:
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
關(guān)于CONST的用法
C語言中的const
C 知識(shí)點(diǎn)
const在函數(shù)前與函數(shù)后的區(qū)別
《C語言深度剖析》關(guān)鍵字介紹七
教你理解復(fù)雜的C/C++聲明  作者 Vikram A Punathambekar
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服