[C++]指針

1. 指針的用處

鏈表

2. 指針的定義

2.1. 基本概念

指針就是指向一個變量或者指針的變量,它裏面存儲的值是一個內存空間的地址。
example
當然,一個指針也可以指向指針。example2

2.2. 代碼實現

int i = 3;
int *p = &i;
int **q = &p;
cout<<p<<" "<<*p<<endl;
cout<<q<<" "<<*q<<" "<<**q;

本程序的輸出結果可能是:

0x22fec8 3
0x22fec4 0x22fec8 3

Hint:
0x22fec8就是變量i的地址
0x22fec4就是指針*p的地址

大家可以舉一反三,還可以定義很多其他類型的指針(比如char,double,long long······),都是同一個原理。

3. 指針進階之交換兩個數的值

3.1. 代碼1

void change(int x,int y){
	int t=x;
	x=y;
	y=t;
}

//main
int a=1,b=2;
change(a,b);
cout<<a<<b;

輸出

1 2

爲什麼a和b沒有交換呢,這是因爲當我們把a和b傳到函數change的時候,參數x和y相當於只是把參數複製了一遍,並沒有改變a和b的值。
所以這裏我們就需要用到指針。我們可以把參數x和y改成a和b的指針。這樣的話,當我們在函數change裏面改變x和y的值後,相當於我們就已經把a和b的值改變了。
代碼如下:

3.2. 代碼2


void change(int *x,int *y){
	int t;
	t=*x;
	*x=*y;
	*y=t;
}

//main
int a=1,b=2;
change(&a,&b);
cout<<a<<b;

這樣我們就可以將a和b的值交換了。

3.3. 代碼3(difficult)

void change(int *x, int *y){
	int *t;
	t=x;
	x=y;
	y=t;
}

//main
int a=1,b=2;
change(&a,&b);
cout<<a<<b;

這一段代碼也是做不到交換的,但是呢,有些人可能會問,這個也用了指針啦,上面那個代碼怎麼就可以這個代碼就不行呢?其實他的主要原因就是由於我們知道函數的參數傳進來的時候,編譯器會把它的參數複製一份,我們這裏呢,複製的是這個指針,但是交換的也是指針,所以還是隻在函數內有效。
也就是說還是隻交換了形參沒有交換實參。

還沒有聽明白嗎?看圖。

最開始:
描述

代碼2執行後
描述
代碼3執行後
描述
通過以上的圖,我們就能很直觀地瞭解到代碼三是如何錯的了。

3.4. 拓展代碼4

不知道大家剛纔有沒有注意到,我們在將a和b傳遞到函數change的時候,在前面加了一個&符號,這個符號的作用是取出變量的地址,所以它叫取址符。

void change(int &x, int &y){
	int t=x;
	x=y;
	y=t;
}

//main
int a=1,b=2;
change(a,b);
cout<<a<<b;

但是在上面代碼中,參數xy變量前面的符號也是&,可是它的作用就不是取址了。這個符號叫引用符,引用符相當於給變量取了個“別名”,實際上他們兩個是同一個變量。所以我們在改變參數x和y的時候,變量a和b也會相應的改變。

4. 數組中的指針

指針不僅可以應用在變量中,它還可以應用在數組中,請看如下代碼。

4.1. 用指針訪問數組

int a[5] = {1, 2, 3, 4, 5};
int *p;
for(p = a; p < a + 5; p++){
	cout<<*p<<" ";
}

輸出

1 2 3 4 5 

在這個代碼中,我們首先定義了指針*p,用來指向數組a的第一個元素a[0],隨後我們每次輸出指針*p,然後將p++(注意這裏的p++是將p原來指向的地址向前挪動一個sizeof(int),而一個sizeof(int)的剛好是4個字節,是一個int所佔用的內存空間。所以在我們當p++之後,p的指針恰好就跳到了數組的下一位)。最後我們要判斷,讓p不要超過數組a所佔的內存空間。

4.2. 數組與指針的關係

數組其實就是一種特殊的指針,所以說訪問數組也可以這麼寫:

a[3] = 5;

等價於:

*(a+3)=5;

數組由於是在內存中連續存儲的,所以,而數組這個a本身他其實也就是一個指針,當我們訪問a[3]時。其實就是在訪問誒這個指針後移三位的位置。那麼它其實也就等價於a+3在訪問裏面的內容啦。
綜上所述,訪問數組也可以這麼寫:

3[a] = 5;

5. 結構體中的指針

5.1. 定義

結構體指針就是指向結構體的指針:

struct node {
	int a;
	double b;
	long long c;
};

//main
node x;
node *p=&x;

這時候p就是一個結構體指針,其類型是node

5.2. 使用

怎麼讀取/寫入結構體指針?

5.2.1. 讀取

->運算符

//read
int a = p->a;
double b = p->b
printf("%lld\n", p->c);

或,如果你願意寫的複雜一點,可以:

//read2
int a = (*p).a;
double b = (*p).b;
printf("%lld\n", (*p).c);

5.2.2. 寫入

也差不多。

p->a = 123;
p->b = 1.023;
scanf("%lld", &(p->a));

複雜的方法就不說了,大家可以舉一反三。

6. 申請/釋放內存

指針申明後是沒有內存空間的,必須申請後纔有:
頭文件:

#include <cstdlib>

6.1. 申請

函數原型:

void* malloc( std::size_t size );

函數的參數就是要申請多少個字節(BYTE)的空間。
用法:

int *p = (int*)malloc(sizeof(int));	

結構體也可以這麼用:

node *q = (node*)malloc(sizeof(node));

6.2. 釋放

函數原型:

void free( void* ptr );

函數的參數就是你剛纔申請的指針。
用法:

free(p);
free(q);

7. 小結

很多人認爲指針是一個很難掌握的語法。但是經過我們這樣一講,大家都對指針有了一個更加清晰的瞭解。所以,看我們多厲害!!!趕快關注我們吧!
這就是今天的內容,明天我們會講一些更加有(kun)趣(nan)的東西。

by sztom and ezlmr

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章