程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 進一步了解const指針

進一步了解const指針

編輯:C++入門知識

問題 今天群裡有人發了個問題,問題如下: 第一個賦值可以,為什麼第二個不行 [cpp]   int * x = NULL;   int const * y = NULL;   y = x;      int ** z = 0;   int const ** n = 0;   n = z     當時我懵了一下,隨即想到可能是int const **的問題,便把代碼改成: [cpp]  int ** z = 0;   int * const * n = 0;   n = z;     編譯通過,以為解決了問題,想也沒想,便發回給提問者。 殊不知,提問者問了好幾個問題後,我又懵了,-_-! 這個const是屬於那一邊的? 可以是 [cpp]   int (* const) * n = 0;     那麼n就是一個指向(int * const)的int指針   也可以是 [cpp]   int * (const *) n = 0;     那麼n就是一個指向(int *)的const int 指針   後來提問者發了書裡面的一句話: 如果const和(或)volatile關鍵字後面緊跟類型說明符(如int, long等),它作用於類型說明符,在其他情況下,const和(或)volatile關鍵字作用於它左邊緊鄰的指針星號。 本人覺得這句話不夠確切,一般情況下,我們會把代碼寫成: [cpp]   const int * p;     這和書中描述的一致,const 此時作用於int。但我們也有另外一種寫法 [cpp]   int const * p;     雖然大家都知道這個const 必定作用於int的,但按照那句話的方法,const找不到作用的地方了。 好吧,這有點鑽牛角了。既然是從書中出來的,還是得用代碼來證明一下。   試驗 回歸到頂部問題,其實就是類型匹配問題,如果類型不匹配,那麼編譯就會報錯,所以通過編譯器(VS2010)來作為我們的裁判,const到底是作用於誰。 先鋪好兩個必須的變量: [cpp]   int * p_to_v_1 = new int(1);;   int * p_to_v_2 = new int(2);     第一試驗 [cpp]  int * * ppTest1 = &p_to_v_1;   ppTest1 = &p_to_v_2;   *ppTest1 = p_to_v_2;   **ppTest1 = 10;   這個應該理解上沒有多大的問題,所以不解釋。 編譯通過,沒報任何錯誤,結論: *ppTest1也是int * 類型。 **ppTest1是int類型。   第二試驗 [cpp]  int const * * ppTest2 = &p_to_v_1;   ppTest2 = &p_to_v_2;   *ppTest2 = p_to_v_2;   **ppTest2 = 10;   這個比較簡單,ppTest2指向的是int const *的指針,所以第三個**ppTest2的賦值編譯器報錯:表達式必須是可修改的左值。 *ppTest2也是int const * (或const int *)類型。 **ppTest2是const int 類型,不可改變,所以賦值時出錯。   第三試驗 [cpp]  int * const * ppTest3 = &p_to_v_1;   ppTest3 = &p_to_v_2;   *ppTest3 = p_to_v_2;   **ppTest3 = 10;   const 來到兩個星號中間,那麼就是上面我遇到的問題了。 編譯器此時報錯是 *ppTest3 = p_to_v2; 這行代碼,錯誤是:表達式必須是可修改的左值。 p_to_v2是指針變量,那麼*ppTest3就是指針常量 *ppTest3是int * const類型。(印證了書中那句話) **ppTest3那一行沒報錯,那麼**ppTest3就是int類型   第四試驗 [cpp]   int * * const ppTest4 = &p_to_v_1;   ppTest4 = &p_to_v_2;   *ppTest4 = p_to_v_2;   **ppTest4 = 10;   報錯的是“ppTest4 = p_to_v2;”這行,錯誤信息和上面例子一樣,那麼ppTest4就是一個指向指針的指針常量,ppTest4是不可更改的。   第五試驗 [cpp]   int const * const * ppTest5 = &p_to_v_1;   ppTest5 = &p_to_v_2;   *ppTest5 = p_to_v_2;   **ppTest5 = 10;   有了前面的基礎,應該很容易判斷這裡報錯的是哪個。 沒錯,第3行和第4行錯誤,*ppTest5是指針常量,**ppTest5是常量。   第六試驗 [cpp]   int * const const * ppTest6 = &p_to_v_1;   ppTest6 = &p_to_v_2;   *ppTest6 = p_to_v_2;   **ppTest6 = 10;   這個定義看起來有點奇怪,雖然會有編譯警告,但是可以通過的。 報錯的只有第3行(*ppTest6 = p_to_v_2;),因為*ppTest6是指針常量。 為什麼第2行不報錯呢?ppTest6是指向指針常量的指針,&p_to_v_2的結果又是指向指針變量的指針。 因為這個賦值的道理就如const int * 類型可以被int *類型賦值一樣(如函數void f(const int * cp)中的參數,f被調用時,傳入的參數可以是const int*,也可以為int *),一個是指向int常量的指針,一個是指向int變量的指針。 這裡的定義(int (* const) (const *) ppTest6 )還有個地方需要注意一下,剛才說了,ppTest6是指向指針常量的指針;而剛好,*ppTest6又是指針常量,那這個定義就相當於 [cpp]   int * const * ppTest6      第七試驗 [cpp]   int * const * const ppTest7 = &p_to_v_1;   ppTest7 = &p_to_v_2;   *ppTest7 = p_to_v_2;   **ppTest7 = 10;   2和3行報錯,ppTest7是常量,*ppTest7也是。   第八試驗 [cpp]   int const * const * const ppTest8 = &p_to_v_1;   ppTest8 = &p_to_v_2;   *ppTest8 = p_to_v_2;   **ppTest8 = 10;   這個2、3、4都報錯,應該不用怎麼解釋了吧。。。   總結一下,剛才那句話大部分還是對的,就差了我剛才提到的那一點,嘿嘿。 如果const和(或)volatile關鍵字後面緊跟類型說明符(如int, long等),它作用於類型說明符,在其他情況下,const和(或)volatile關鍵字作用於它左邊緊鄰的指針星號。   解決問題 剛才說明了const在不同位置所起的不同作用,現在回過頭來看原先的問題: [cpp]   int * x = NULL;   int const * y = NULL;   y = x;      int ** z = 0;   int const ** n = 0;   n = z   現在來看這些指針,應該比較明確: z就是指向int *的指針; 而n就是指向const int *的指針; n和z最終指向類型(一個是int, 一個是const int)是不一樣的,所以賦不了值。 就如以下代碼 [cpp]   int * x = NULL;   int * const y = NULL;   y = x;    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved