国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

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

發布時間:2016-2-18 14:12    發布者:designapp
關鍵詞: C語言 , const
         或許還有不少人對于const修飾符理解的并不深刻,都只是停留在一個比較淺的層面上,僅僅是在讀別人代碼的時候看到了const修飾符的使用,自己的寫代碼的過中從未使用過,所以自然對于const修飾符比較陌生。那么到底什么是const修飾符,我們在自己編寫C語言代碼的過程中又該如何有效的使用const修飾符呢,現在讓我們來學習下const修飾符的使用。
  const在C語言中算是一個比較新的描述符,我們稱之為常量修飾符,即就是說其所修飾的對象為常量。當你代碼中想要設法阻止一個變量被改變,那么這個時候可以選擇使用const關鍵字。在你給一個變量加上const修飾符的同時,通常需要對它進行初始化,在之后的程序中就不能再去改變它。
  可能有的人會有一個疑問,我們不是有在C中有預處理指令#define VariableName VariableValue 可以很方便地進行值替代,干嘛還要引入const修飾符呢?!這是因為預處理語句雖然可以很方便的進行值得替代,但它有個比較致命的缺點,即預處理語句僅僅只是簡單值替代,缺乏類型的檢測機制。這樣預處理語句就不能享受C編譯器嚴格類型檢查的好處,正是由于這樣,使得它的使用存在著一系列的隱患和局限性。
  在講解const修飾符之前,我們在此首先給出const修飾符的幾個典型作用:
  1. const類型定義:指明變量或對象的值是不能被更新,引入目的是為了取代預編譯指令
  2. 可以保護被修飾的東西,防止意外的修改,增強程序的健壯性;
  3. 編譯器通常不為普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成為一個編譯期間的常量,沒有了存儲與讀內存的操作,使得它的效率也很高。
  4. 可以節省空間,避免不必要的內存分配。
  接下來看看具體的使用。
  一、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就是修飾指針本身,即指針本身是常量。
  還是給個代碼來加深下大家的印象吧。
  #include
  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;
  }
  運行結果如下:
  


  簡單的來分析下吧,因為r指向的是ss的地址,所以修改r指向的地址單元的值的同時ss的值也隨之變化。
  結合上述兩種const修飾的情況,我們現在應該可以完成如何聲明一個指向const int類型的const指針,如下:
  const int * const r=&ss;
  這個時候我們既不能修改*r的值也不能修改r的值。
  接下來看看const用于修飾常量靜態字符串,例如:例如:
  const char* str="fdsafdsa";
  如果沒有const的修飾,我們可能會在后面有意無意的寫str[4]='x'這樣的語句,這樣會導致對只讀內存區域的賦值,然后程序會立刻異常終止。有了const,這個錯誤就能在程序被編譯的時候就立即檢查出來,這就是const的好處。讓邏輯錯誤在編譯期被發現。
  二、const在函數聲明時修飾參數
  void *memmove( void* dest, const void* src, size_t count ); 這是標準庫中的一個函數,在頭文件#include 中聲明,其功能為由src所指內存區域復制count個字節到dest所指內存區域。用于按字節方式復制字符串(內存)。它的第一個參數,是將字符串復制到哪里去(dst),是目的地,這段內存區域必須是可寫。它的第二個參數,是要將什么樣的字符串復制出去,我們對這段內存區域只做讀取,不寫。于是,我們站在這個函數自己的角度來看,src 這個指針,它所指向的內存內所存儲的數據在整個函數執行的過程中是不變。于是src所指向的內容是常量。于是就需要用const修飾。另外需要強調的一點就是src和dest所指內存區域可以重疊,但復制后dest內容會被更改。函數返回指向dest的指針。
  例如,我們這里這樣使用它。
  #include
  #include
  int main(int argc, char* argv[])
  {
  const char* str="hello";
  char buf[10];
  memmove(buf,str,6);
  printf("%s\n",buf);
  return 0;
  }
  運行結果如下:
  


  如果我們反過來寫,memmove(str,buf,6);那么編譯器一定會報錯。事實是我們經常會把各種函數的參數順序寫反。事實是編譯器在此時幫了我們大忙。如果編譯器靜悄悄的不報錯,即在函數聲明void *memmove( void* dest, const void* src, size_t count ); 處去掉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'; //合法
  三、const作為全局變量
  在程序中,我們要盡可能少的使用全局變量。因為其作用域是全局,所以程序范圍內都可以修改它的值,從而導致了全局變量不能保證值的正確性,如果出現錯誤非常難以發現。如果在多線程中使用全局變量,你的程序將會錯的一塌糊涂。多線程會修改另一個線程使用的全局變量的值,如果不注意,一旦出錯后果不堪設想。所以在這種情況下萬不得意不要使用全局變量。我們要盡可能多的使用const。如果一個全局變量只在本文件中使用,那么用法和前面所說的函數局部變量沒有什么區別。如果它要在多個文件間共享,那么就牽扯到一個存儲類型的問題。
  有兩種方式。
  1.用extern
  例如
  /* pi.h */
  extern const double pi;
  /* pi.c */
  const double pi=3.14;
  然后其他需要使用pi這個變量的,包含pi.h
  #include pi.h
  或者,自己把那句聲明復制一遍就好。這樣做的結果是,整個程序鏈接完后,所有需要使用pi這個變量的共享一個存儲區域。
  2.使用static,靜態外部存儲類
  /* constant.h */
  static const double pi=3.14;
  需要使用這個變量的*.c文件中,必須包含這個頭文件。前面的static一定不能少。否則鏈接的時候會報告說該變量被多次定義。這樣做的結果是,每個包含了constant.h的*.c文件,都有一份該變量自己的copy,該變量實際上還是被定義了多次,占用了多個存儲空間,不過在加了static關鍵字后,解決了文件間重定義的沖突。壞處是浪費了存儲空間,導致鏈接完后的可執行文件變大。通常來說,對于存儲空間字節的變化不是太大的情況下,不是問題。好處是,你不用關心這個變量是在哪個文件中被初始化的。
  下面再來看看一段代碼:
  #include
  int main()
  {
  const int a=12;
  const int *p=&a; // 這個是指向常量的指針,指針指向一個常量
  p++; //可以指針可以自加、自減
  p--; //合法
  int const *q=&a; // 這個和上面const int *p=&a;是一個意思
  int b=12;
  int * const r=&b; //這個就是常量指針(常指針),不能自加、自減,并且要初始化
  //r++; //編譯出錯
  const int * const t=&b; //這個就是指向常量的常指針,并且要初始化,用變量初始化
  //t++; //編譯出錯
  p=&b; //const指針可以指向const和非const對象
  q=&b; //合法
  return 0;
  }
  為了便于代碼的閱讀理解,在此就直接在代碼后面加注釋,就不在這兒做過多的講解了。
  綜上所述,const 的好處,是引入了常量的概念,讓我們不要去修改不該修改的內存。直接的作用就是讓更多的邏輯錯誤在編譯期被發現。所以我們要盡可能的多使用const。以上內容難免有錯,如果錯誤,請糾正!如需轉載,請注明出處!
                               
               
本文地址:http://m.qingdxww.cn/thread-160861-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 使用SAM-IoT Wx v2開發板演示AWS IoT Core應用程序
  • 使用Harmony3加速TCP/IP應用的開發培訓教程
  • 集成高級模擬外設的PIC18F-Q71家族介紹培訓教程
  • 探索PIC16F13145 MCU系列——快速概覽
  • 貿澤電子(Mouser)專區
關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 色爰情人网站| 国产呦精品一区二区三区网站| 岛国片免费看| 美女全光末满18勿进| 午夜福利电影网站鲁片大全| 亚洲欧美日产综合在线看| 亚洲a免费| 日韩欧美亚洲| 青青青草免费| 亚洲高清在线| 亚洲免费观看网站| 亚洲国产成人久久77| 4438成人情人网站| 久久99热在线观看7| 小草高清视频免费直播| 日韩欧美精品综合久久| 色男人综合| 十六一下岁女子毛片免费| 一卡二卡三卡四卡无卡在线 | 强壮的公次次弄得我高潮韩国电影 | 一区二区福利视频| 亚洲综合美腿丝国产一区| 成人免费公开视频| 欧美熟妇互舔20p| 天天澡夜夜澡人人澡| 日韩精品视频在线免费观看| 色噜噜色噜噜天天拍一拍| 亚洲国产精品成人综合色在线婷婷 | 亚洲综合激情另类图片专区| 日本巨黄视频| 在线 v亚洲 v欧美v 专区| 一本大道在线观看| 国产人妖一区二区| 亚洲 欧美 国产 综合 在线| 思思玖玖玖在线精品视频| 四虎海外在线永久免费看| 在线天堂中文在线资源网| 一个人看的hd免费视频| 久久中文字幕亚洲| 全黄a免费一级毛片人人爱| 日本免费观看完整视频|