文章目錄
1. 指針的用處
鏈表
2. 指針的定義
2.1. 基本概念
指針就是指向一個變量或者指針的變量,它裏面存儲的值是一個內存空間的地址。
當然,一個指針也可以指向指針。
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;
但是在上面代碼中,參數x
和y
變量前面的符號也是&
,可是它的作用就不是取址了。這個符號叫引用符,引用符相當於給變量取了個“別名”,實際上他們兩個是同一個變量。所以我們在改變參數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