第六章 指標和型別限定符

weixin_33912246發表於2016-11-07

型別限定符主要是指const和volatile,前者用於表明某個變數是不可修改的,後者表示該變數是可變的。由於在學習工作中會遇到大量由const修飾的指標,而且修飾指標的不同的位置的效果不一樣,所以,本文將著重討論這種情況。

關鍵字const並不能把變數變成常量,它不會把變數從變數區移到常量區,它只是提醒編譯器不能給這個符號賦值,但是它不能防止通過修改和這個變數掛鉤的其它符號以達到修改這個變數的目的。

例如:

int a = 1; 
const int *pa = &a;
雖然我們不能通過*pa來修改a的值,但是我們可以通過a來修改a的值。

關於有const修飾和無const修飾的變數之間賦值要符合一些規則,這些規則是:

規則1:無const修飾符的變數之間可以按照普通變數的規則相互賦值,有相同const修飾符的變數之間也可以按照普通變數的規則相互賦值。
規則2:只能將無const修飾的變數賦值給有const修飾的指標,反之不行。
  例如:int a = 1; const int *pa = &a;可以,但是const int a = 1; int *pa = &a;則不行
規則3:涉及到const的指標之間賦值必須滿足以下兩個條件之一,否則會產生錯誤。
  條件1.兩個運算元都是指向有限定符或無限定符的相容型別的指標
  條件2.左邊指標所指向的型別必須具有右邊指標所指向型別的全部限定符。
  例如:const int*p; int *a; 則,p=a;可以,而a=p;不可以
  例如:const int**p; int **a; 則,p=a;不可以,而a=p;不可以
  注:第一個例子中,p=a;中的p和a都是一個指標,左邊指標所指向的型別是const int 而右邊的指標所指向的型別是int。
    右邊指標所指向型別的限定符是int,而左邊指標所指向的型別的限定符是int+const,有int,所以它符合條件2,是合法的。
    反之,a所指向的型別的限定符中沒有const,而p有,所以,a=p非法。
  注:第二個例子中,p和a都是一個指標,一個是指向const int*型,一個是指向int*型。
    也就是說它們所指向的資料還是一個指標,且前一個指標是指向const int型的,後一個指標是指向int型的,這裡的const不是用來修飾p所指的引數的。
    即p和a所指的引數都是無const修飾的指標,所以它們不符合條件2。
    但是p所指的引數是個指向const int型的指標,a所指的引數是個指向int型引數的指標,它們是不相容的。所以,它們之間賦值是錯誤的。
  注:根據這個道理,我們可以知道,若是,int* const *p; int **a;,則p=a;就是合法的。
    因為p和a都是個指標,而p指向個有const修飾的指標,a指向個沒有const修飾的指標,並且這個指標都是指向相同的型別int型。

為了說明const放在多維指標的不同地方的不同意義,同時不至於使講解過程過於複雜,我們選擇二維指標作為例子。

const int**p;    是指不能用**p來修改p所指向的位置所指向的位置的值。
int* const *p;   是指不能用*p來修改p所指向的位置的值。
int **const p;   是指不能用p修改p的地址。
注:再次說明,用const進行限定只能讓編譯器保證不通過這個符號來修改這個變數,但不能防止其他相關的變數修改它。
  例如,我們可以將一個const 型的指標強制轉換成非const型的,再利用這個指標修改其中的值。
  但是,這種寫法可以提醒程式設計師不要修改這個引數的內容,
  所以,它在函式引數中很常用。
  當然,指標強制轉換,可是強大無比的。
注:const記憶法,const用於修飾其後第一個*。

相關文章