可愛的指針(一)

可愛的指針(一)

基本介紹

在互聯(lián)網(wǎng)時(shí)代,幾乎人人都會(huì)使用互聯(lián)網(wǎng)來(lái)瀏覽信息。自互聯(lián)網(wǎng)2.0以后,網(wǎng)頁(yè)也變得越來(lái)越豐富。一個(gè)網(wǎng)頁(yè)可以包含各種形式的信息,比如文字、圖片、視頻等。網(wǎng)頁(yè)及其中的圖片、視頻都可以通過(guò)網(wǎng)址來(lái)獲得。比如鏈接https://www.nasa.gov/sites/default/files/styles/full_width_feature/public/thumbnails/image/potw2045a.jpg對(duì)應(yīng)一張NASA的星云圖。
[圖片上傳失敗...(image-f2f3ba-1605971654846)]
給定一個(gè)鏈接(或者稱之為地址),瀏覽器會(huì)根據(jù)地址向?qū)?yīng)的服務(wù)器獲取圖片(內(nèi)容)。指針也是類似的概念。我們可以把網(wǎng)絡(luò)地址看成指向網(wǎng)絡(luò)資源的指針。

在計(jì)算機(jī)內(nèi)存中,每一個(gè)資源都對(duì)應(yīng)了一個(gè)地址。每當(dāng)我們用程序語(yǔ)言定義一個(gè)變量,計(jì)算機(jī)都會(huì)在內(nèi)存中開辟一個(gè)特定大小的存儲(chǔ)空間,用來(lái)存儲(chǔ)對(duì)應(yīng)變量的值。
[圖片上傳失敗...(image-57e600-1605971654846)]
每一個(gè)變量都有三個(gè)要素:(1)變量名,(2)變量的地址,(3)變量的值。在上面的圖中,變量c的地址為0x0012FF74,變量c的值為76。不難發(fā)現(xiàn),變量和上面例子當(dāng)中的NASA星云圖是很像的。和指向星云圖的指針(網(wǎng)址)類似,我們可以把某個(gè)變量的地址稱為指向該變量的指針。

有趣的是,計(jì)算機(jī)是可以通過(guò)變量的地址(指針)訪問或改變變量的內(nèi)容。拋開指針,我們可以通過(guò)cout<<c<<endl;來(lái)打印變量c的值。在使用指針來(lái)打印變量之前,我們首先需要獲得變量的指針(地址)。C++語(yǔ)言中,可以通過(guò)&c獲得變量c的地址(指針)。如果我們想把&c存放在一個(gè)變量里,我們就需要定義一個(gè)指針變量 int* pointerpointer作為指針變量,它是用來(lái)存儲(chǔ)指針的,pointer本身作為一個(gè)變量,也有一個(gè)對(duì)應(yīng)的地址,這個(gè)地址和它本身存儲(chǔ)的地址是不同的)。pointer = &c稱作指向變量c的指針。

int c = 76; //定義int類型變量c,并賦值76
int *pointer; //定義名字為pointer的指針變量,*表示pointer類型為指針類型
pointer = &c; //將變量c的地址賦值給指針變量pointer

這里,int *中的int稱為指針類型的基類型,基類型可以幫助程序確定指針指向的變量在內(nèi)存中所占空間的大小。

有了指針變量之后,如何通過(guò)指針變量訪問指針變量指向的變量?jī)?nèi)容呢?(如何利用pointer訪問變量c的值76呢?)可以使用指針運(yùn)算符*實(shí)現(xiàn)。使用*pointer,我們可以獲得pointer所指向的存儲(chǔ)單元的內(nèi)容。這里,pointer所指向的存儲(chǔ)單元的內(nèi)容是變量c(注意,內(nèi)容是變量c而不是76,因?yàn)槲覀兛梢詫?shí)現(xiàn)操作*pointer = 72,其含義等于c = 72)。

Example 1:

void main(){
  int c;
  int *pointer;
  c = 76;
  pointer = &c;
  cout<<*pointer<<endl;
}

這里,cout<<*pointer<<endl;相當(dāng)于cout<<c<<endl;所以結(jié)果打印出76。注意,在使用指針變量時(shí),一定要先對(duì)其進(jìn)行賦值,然后才能使用指針變量訪問或者改變指向變量的值。

Example 2:

void main(){
  int akey = 0,b = 0;
  int *p = NULL, *q = NULL;
  akey = 66;
  p = &akey;
  q = &b;
  *q = *p;
  cout<<"b = "<<b<<endl;
  cout<<"*q = "<<*q<<endl;
}

這個(gè)結(jié)果會(huì)打印出

b = 66
*q = 66

程序的邏輯很簡(jiǎn)單,最關(guān)鍵的一行就是*q = *p;??梢园堰@一行理解為b = akey;,即把akey的值賦值給b。

Example 3:

void main(){
  int *p1, *p2, *p;
  int a,b;
  cin>>a>>b;
  p1 = &a; p2 = &b;
  if (a < b){
    p = p1;
    p1 = p2;
    p2 = p;
  }
  cout<<"a = "<<a<<", b = "<<b<<endl;
  cout<<"max = "<<*p1<<", min = "<<*p2<<endl;
}

這里,我們輸入3 5,會(huì)打印出

a = 3, b = 5
max = 5, min = 3

這個(gè)程序的核心邏輯在如果a < b,則將小數(shù)a的指針p1和大數(shù)b的指針p2交換。交換后,p1會(huì)指向大數(shù),p2會(huì)指向小數(shù)。(注意,只是交換了指針,并未交換指針?biāo)赶虻膬?nèi)容。)

Discussion of *&a

定義整型變量a:int a = 3;,&a代表我把它取得整型變量a的地址;*&a表示取地址&a處相應(yīng)的內(nèi)容(變量a);所以,*&a等價(jià)于a

Discussion of &*pointer

定義整型變量a:int a = 3;并且定義一個(gè)指向變量a的指針變量pointerint *pointer = &a;。*pointer等價(jià)于整型變量a;&*pointer等價(jià)于&a;(*pointer)++等價(jià)于a++。

Discussion of iPtr++

假設(shè)iPtr所代表的地址是0x00000100,
iPtr指向一個(gè)整型元素(占4字節(jié)),則iPtr++等于iPtr+1*4=0x00000104;
iPtr指向一個(gè)實(shí)型元素(占4字節(jié)),則iPtr++等于iPtr+1*4=0x00000104;
iPtr指向一個(gè)字符元素(占1字節(jié)),則iPtr++等于iPtr+1*1=0x00000101。

指針與數(shù)組

指向數(shù)組元素的指針的定義、賦值、使用與基本變量完全相同。我們可以看如下的例子:

Example 4

void main(){
  int a[5] = {1,2,3,4,5};
  int *p = &a[3];
  cout<<*p<<endl;
  *p = 100;
  cout<<a[3]<<endl;
}

程序的的核心在int *p = &a[3];*p = 100;。這里,*p = 100;相當(dāng)于a[3] = 100;。所以打印出:

4
100

以上是指向數(shù)組元素的指針的使用,而我們需要關(guān)注的是指向數(shù)組的指針。

在C++中,數(shù)組名代表數(shù)組首元素的地址。定義int a[10],則數(shù)組名a代表數(shù)組a[10]中第一個(gè)元素a[0]的地址;即a&a[0]等價(jià);若有int *p,則p = &a[0]p = a等價(jià)。(注意,a是地址常量,不能給a賦值)

在定義int a[10]存放10個(gè)int類型的連續(xù)空間之后,我們可以使用a + n來(lái)獲得數(shù)組a中第n+1個(gè)元素的地址。(a+1是數(shù)組a[10]中第二個(gè)元素a[1]的地址。)同時(shí),指向數(shù)組元素的指針可以用做下標(biāo):[]*的作用相同,比如p[i]*(p+i)等價(jià)。(使用*(p+i)要注意數(shù)組下標(biāo)越界的情況?。?/p>

Discussion

如果定義int a[5] = {1,2,3,4,5}; int *p;,假設(shè)當(dāng)前i=3, a[4] = 4,則t = *p--相當(dāng)于t = a[i--],先做*p運(yùn)算。

  • *++p相當(dāng)于a[++i],先將p自加,然后再做*運(yùn)算;
  • *--p相當(dāng)于a[--i],先將p自減,然后再做*運(yùn)算;
  • *p++相當(dāng)于a[i++],先做*運(yùn)算,在做p自加;
  • *p--相當(dāng)于a[i--],先做*運(yùn)算,在做p自減;

Example 5

利用指針實(shí)現(xiàn)數(shù)組a的輸入和輸出:

int main(){
  int *p, i, a[10];
  p = a;
  for(i = 0; i < 10; i++)
    cin>>*p++;
  p = a;
  for(i = 0; i < 10; i++)
    cout<<*p++;
  return 0;
}

輸入1 2 3 4 5 6 7 8 9 10
輸出1 2 3 4 5 6 7 8 9 10

Example 6

void main(){
 int a[5] = {1,2,3,4,5};
 int *p = &a[3];
 *p = 100;
 cout<<*p++<<endl;
 cout<<*p--<<endl;
 cout<<*--p<<endl;
}

這個(gè)例子主要看*操作和++或者--的優(yōu)先級(jí)。*p++表明先計(jì)算*p,之后再p++,此時(shí)輸出100*p等價(jià)于a[4];*p--先輸出a[4]的值:5,再自減,此時(shí)*p等價(jià)于a[3];*--p首先執(zhí)行--p,此時(shí)*p等價(jià)于a[2],再輸出a[2]的值:3。故最后的輸出為

100
5
3

以上是指針和一維數(shù)組之間的一些問題。下一篇將會(huì)簡(jiǎn)單介紹指針和二維數(shù)組之間的一些操作。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容