指針
-
指針變量定義
在計算機內部每一個字節單元都有一個編號,稱爲地址。
內存單元的地址稱爲指針,存放指針的變量稱爲指針變量。
請記住上面兩句話,因爲這就是指針的本質。
計算機位數對應於地址的字寬,32位計算機的字寬就是32位的,也就是4個字節。(
所有類型(int*,char*,struct*,數組等)的指針都是32位的,即4個字節的
)
爲什麼呢?因爲計算機的位數代表了其尋址能力,因爲指針變量存放的是指針,也就是32位二進制數據,也就是4個字節。所以在遇到 別人讓你求sizeof(指針變量),這個問題就變得很簡單了,現在我們知道了32位的機器下面,這個值是4,64位機器下面這個值是8。好了,下次別人再問你這個問題,你可以反問他:你說的是多少位的機器?
指針定義形式如下:
類型說明符* 變量名
- *表示一個指針變量,類型說明符表示指針所指向的數據類型。
- 雖然所有的指針都等長,但是還要指明數據寬度,因爲對指針變量的其他操作都涉及都涉及指針變量的數據寬度。(即指針所指向數據的類型)
-
指針變量的賦值
指針變量定義以後,不能隨便使用。指針變量的值只能是其所指向的變量的地址。不能是其他數據。
C語言中變量的地址是有編譯系統分配的,用戶不知道的。但是變量的地址可以用&運算符來查看變量的地址。形式如下:
&變量名
// & —>取地址符 -
指針變量的引用
- *------>指針運算符(間接存取運算符)
- &------>取地址運算符
指針變量P的目標變量m,因此*P,m,*(&m)表達式的含義相同。
- P-----指針變量,它的內容是地址
- *P-----指針所指向的對象,它的內容是數據(即其所指向的變量的值)
- &P------指針變量所在的存儲區域的地址(注意這裏的說法)
-
指針的運算
指針運算是以指針變量所存放的值(地址量)作爲運算量來進行的運算。指針的運算是指就是地址的計算。定義指針變量P:
-
p+n---->指針向地址方向大的方向移動n個數據
-
p-n----->指針向地址方向小的地方移動n個數據
-
+±----->++p,p++
-
– ------>–p,p–
-
p-q--------->兩個指針之間相隔數據元素的個數
p + x---->實際內存單元的地址量:p+x*sizeof(p指向的數據類型)
-
注意:兩個指針相減的結果值不是地址量,而是兩個指針間的元素個數
指針的關係運算:
- 具有不同數據類型的指針之間的關係運算沒有意義。指向不同獨居區域的兩個指針之間的,關係運算也沒有意義。
量個重要的表達式:
- *p++–>同一優先級,從右向左運算,相當於*(p++),表達式的作用是在原p的值的基礎上進行間接操作,將p值加1。表達式的值是提取原p的內容。(++在後,p先參與運算*P,再把p值後移一個數據寬度)
-
-
空指針
空指針即指真指向了零號地址,可以用:int *p = 0;
C 中一般用NULL來代表0,它可以表明一個指針當前爲指向任何變量。
在定義指針時,最好將指針初始化爲0。
-
指針和數組
數組名是一個地址,指針的一次相加是以其所指向的對象的數據寬度爲單位進行移動。
數組名 +i ---->數組名[i]
指針的效率要高於數組下標。
[]是變址運算符,*(a+i)和a[i]無條件等價
假設指針P指向數組a的首元素,那麼素組元素有以下幾種表達方式:a[i]<—>*a[i]<—>p[i]<—>*(p+i)
數組名是地址常量,指着是地址變量,數組名可以被作爲指針參與運算,但是不能被賦值
-
指針與二維數組
二維數組可以看做是以一維數組爲元素的特殊的一維數組。參與運算時以行爲單位進行移動,也被稱爲行地址。二維數組a[3][2]
- a[]—>第一行第一列元素的地址
- a---->第一行的首地址,也等於第一行第一列元素的地址
- a+1—>第二行第一列元素的地址
a[1][1]<->*(&(a[1][0])+1)<->*(a[1]+1)<->*(*(a+1)+1)
當偏移量前的元素單元是整個素組時,偏移的單元是行,當偏移量前的元素單元是行時,偏移的單元是行中的元素。
-
多級指針
指向一級指針變量的指針稱爲二級指針。
二級指針:
<存儲類型> <數據類型> **<指針名>
-
指針數組
指由若干個相同存儲類型和數據類型指針變量構成的集合。
定義形式:
<儲存類型> <數據類型> *<指針變量名> [<大小>]
指針數組名實際爲二級指針。
-
const與指針
const關鍵字的作用是使得變量常量化,即限制變量爲只讀。
const int *a;
int const *a;
int *const a;
const int *const a;
前兩個位限制指針變量a所指向的變量的值不能被修改;第三種形式時限定指針變量a的不能被改動。第四種爲限制指針變量的值及其所指向的變量的值都不能修改。
總結:
- 1.指針變量名與const之間沒有任何修飾符,限制指針變量爲只讀。即限定指針變量存儲的地址值不能被改變
- *2.指針指向的值爲只讀,const修飾(int )或者修飾*
-
void指針
- void類型的指針變量是一種不確定的指針變量,它可以通過強制類型轉換,才能讓指針變量指向其他數據類型。
- 在沒有強轉之前void *類型的指針不能進行任何數據運算。
-
字符指針
- 字符指針就是存儲字符變量的地址
- 利用字符數組對字符串進行遍歷
- 雖然字符數組名是字符串的首地址,但是數組名是一個常量,其值是不能改變的(不能進行自加、自減、賦值等操作),但如果把字符數組的首地址賦值給一個字符指針變量,就可以移動這個字符指針變量來訪問每一個字符。
字符指針數組:
-
若數組中存儲了若干個字符串的地址,則這個數組就叫做字符指針數組。例如:
char s1[] = {"welcime"}; char s2[] = {"to"}; char s3[] = {"wuhan"}; char *a1[] = {s1,s2,s3}; char *a2[] = {"welcome","to","wuhan"};
上面這段代碼中,a1和a2都是字符指針數組。a1,a2存儲的是一維指針的地址,所以,a1,a2也是二級指針。