1. 程式人生 > >C語言教程(5)之指標

C語言教程(5)之指標

指標:(C語言的靈魂)

記憶體的儲存是以一個位元組為一個編號,也就是8位合在一起給一個編號,不是0,1就給編號。

記憶體分為很多個單元,每個單元就會分配一個編號

地址:記憶體單元的一個編號。而指標和地址一個概念的。也就是說指標就是地址

普通變數:只能存放一個值。

指標變數:同樣是一個變數,但是指標變數存放其他變數的地址。

*p代表的是p所指向的那個變數。在上圖中*p和i是同一個東西,但是*p和p不是同一個東西。

在上圖中,int * p是一個宣告,開頭的int * 是他的資料型別。P是變數的名字。不能理解我定義了一個整形變數,這個整形變數的名字叫做*p。所謂int *型別

,實際就是存放int 變數地址的型別。

*p代表的是以p的內容為地址的變數。

解析:p的內容是一個地址,在上圖中,p的內容就是i的地址,*p其指向的變數當然就是i變量了。

指標和指標變數:

指標就是地址,地址就是指標。

地址就是記憶體單元的編號。

指標變數:存放地址的變數。而指標只是一個值,這個值是記憶體單元的一個編號。指標變數才是一個變數,他裡面才可以存放資料。

指標和指標變數是兩個不同的概念,但是需要注意的是,通常我們在敘述時會把指標變數簡稱為指標,實際他們含義並不一樣。

指標的重要性:                                                               

指標的分類

指標的定義:

·地址:記憶體單元的編號,是一個從0開始的非負整數

範圍:cpu對記憶體是通過控制、資料、地址三條匯流排來進行控制的。

控制:cup會先把記憶體中的資料讀入,進行處理後,在返回給記憶體,然後記憶體在把資料寫入硬碟。

資料:用於資料的傳輸,不管是把記憶體中的資料傳送給cpu,還是把cpu的資料寫如記憶體條,都是由資料線來完成的,但是資料傳輸的方向則是由控制線來控制的。

地址:地址線則是確定資料要寫入記憶體中的那個單元。

所謂的一個單元就是一個位元組

一條地址匯流排能控制2的1次方,一般的機器有32個地址線,最終能夠控制2的32個單元,而每個單元是八位,而最終我們的記憶體能夠儲存2的32次方*8位。

則換算為G的話,最終大小為4G.那麼地址匯流排的範圍則是4G大。

指標:指標就是地址,地址就是指標。

      指標變數就是存放記憶體單元編號的變數。

      指標變數和指標是兩個不同的概念

      指標的本質就是一個操作受限的非負整數。

指標不能進行算術運算-相加 除。但是能相減。

如果兩個指標變數指向的是同一塊連續空間的不同儲存單元,則這兩個指標變數才可以相減。類似於同一個小區同一樓層六牌號相減表示兩房間隔。這時才有現實意義。

基本型別的指標:

Int *p:p只能存放int型別的地址。

P = & i:把i的地址賦給p。然後p就指向了i,*p就等於i。其實就是

1:該語句儲存了i的地址。

2:p儲存了i的地址,所以p指向i。

3:p既然指向i,*p就是i。

*p:表示以p的內容為地址的變數。

*p:p是有指向的,p裡面是個垃圾值,*p則是說以p的內容為地址的變數。因為不知道p的值是多少,所以不知道*p到底代表的是那個變數。而*p = i,i=5,最終的結果就是把5賦給了一個所不知道的單元。

  

上圖中,第一個error是資料型別不符合,不能相互轉

換。*q代表的是整形,因為*q代表的是以q的地址為內容的變數。而p是地址(int *)型別。第二個error

同樣有錯,因為q沒有賦值。

經典指標程式-互換兩個數字

1:先用函式來互換:

最終的輸出結果沒有互換,因為函式的a,b已經執行

完成,分配給記憶體的空間已經釋放了,所以最終a,b

的值還是主函式a,b的值。互換的是形參的a,b。和

主函式沒有關係。

在上圖中,輸出的值也是沒有互換的,輸出的同樣是3

,5,需要注意的是,互換的只是p、q的內容,區域性函式變化了,但是主函式是沒有變化的。

最終正確的程式:

*號的三種含義

1:乘法

2:定義指標變數。Int  * p,定義了一個名字叫p的變

量,int *表示p只能存放int變數的地址。

3:指標運算子。該運算子是放在已經定義好的指標變

量的前面。如果p是一個已經定義好的指標變數,則*

P表示以p的內容為地址的變數。

注意理解形參,實參,和區域性變數的關係。

指標可以是函式返回一個以上的值:

不使用指標的話,只能使用用return來返回一個值。

如何通過被調函式修改主調函式普通變數的值

指標和陣列

指標和一維陣列:

(陣列名   下標與指標關係 指標變數的運算)

·一維陣列名:一維陣列名是個指標常量,他存放的是

一維陣列第一個元素的地址。

常量是不能被改變的,也就是說,一維陣列名是不能被

改變的。

陣列名a存放的是一維陣列第一個元素的地址,也就是

a  =  &a。

printf(“%#X\n”,&a[0]); ===== printf(“%#X\n”,a);

指標和二維陣列:

下標和指標的關係

·如果p是個指標變數,則p[i]永遠等價於*(p+i)

確定一個一維陣列需要幾個引數,【如果一個函式要處理一個一維陣列,則形參需要接收該陣列的哪些資訊。】

確定一個一維陣列需要兩個引數

1:陣列名,從陣列的名稱就可以知道陣列的第一個值,因為一維陣列的名稱就是陣列的第一個元素的地址。

2:是陣列的個數。來計算該陣列有多少個值。

區別於  字串(只需要一個引數—首地址)

因為字串預設其後面都有一個“/0”作為結束標誌。而陣列並沒有相關約定。

在上圖中,a是個指標變數,所以上面區域性函式f的pArr則要定義成指標函式才可以,而len則是int型別。代表接收的是整型的數字。 

在上圖中因為陣列a的名稱代表的是a的第一個元素的地址,所以在函式f中所定義的指標變數pArr和a是相同的,因為a也是指標型別。也就是說pArr=a=a[0],pArr[1]=a[1]=*(pArr+1)=*(a+1),pArr[2]=a[2]=*(pArr+2) =*(a+2).所以在f函式中pArr[3]=a[3],所以第二個printf輸出的結果是88.

總結:pArr[i] = a[i] = *(pArr+i) = *(a+i)

在沒有學習指標時,可將a[3]認為是陣列中第4個元素,但現在應該對其內部原理有更深刻認識。

這裡下標也當成指標了,從首元素開始向後移動3個,即指向第4個元素。

在上圖中因為陣列a的名稱代表的是a的第一個元素的地址,所以在函式f中所定義的指標變數pArr和a是相同的,因為a也是指標變數型別。也就是說pArr=a=a[0],pArr[1]=a[1]=*(pArr+1)=*(a+1),pArr[2]=a[2]=*(pArr+2) =*(a+2).

通過上圖,我們知道,我們在f函式中修改陣列的值,相當於修改主函式中相對應的值。

何謂變數地址  / 一個指標佔幾個位元組

Sizeof(變數名/資料型別) 其返回值就是該變數或資料型別所佔位元組數。

一個指標變數無論其指向變數佔幾個位元組,其本身所佔大小都是4位元組。

*p具體指向幾個位元組,要靠前面型別確定,如果為int則為4位元組,如果double則佔8位元組。

CPU  與 記憶體 互動時 有32根線,每根線只能是1或0兩個狀態,所有總共有232個狀態。

1 個狀態 對應 一個單元。如全為0 全為1 等。

記憶體中第一個單元,即32根線狀態全為0。

0000 0000 0000 0000 0000 0000 0000 0000

其大小為4位元組                    

所有每個地址(硬體所能訪問)的用4個位元組儲存(而不是一 位bit)

一個變數的地址—用該變數首位元組的地址表示。這也就是為什麼指標變數始終只佔4位元組的原因。