C++学习笔记7[指针]
C++學習目錄鏈接:
C++學習筆記目錄鏈接(持續更新中)
文章目錄
- 一、變量和指針
- 1.指針的聲明
- 2.指針的賦值
- 3.關于指針使用的說明
- 4.指針運算符和取地址運算符
- 5.指針運算
- 二、指針和數組
- 1.數組的存儲
- 2.指針與一維數組
- 3.指針與二維數組
- 4.指針與字符數組
- 三、指向函數的指針
- 四、引用
- 1.使用引用傳遞參數
- 2.使用指針傳遞參數
- 3.數組作為函數參數
- 五、指針數組
一、變量和指針
????系統的內存就像是帶有編號的小房間,如果想使用內存就需要得到房間號。如圖所示,定義一個整型變量i,它需要4個字節,所以編譯器為變量i分配了編號從4001到4004的房間,每個房間代表一個字節。
????各個變量連續地存儲在系統的內存中,如圖所示,兩個整型變量i和i存儲在內存中。
????在程序代碼中通過變量名來對內存單元進行存取操作,但是代碼經過編譯后已經將變量名轉換為該變量在內存的存放地址,對變量值的存取都是通過地址進行的。例如語句“i+j;” 的執行過程是根據變量名與地址的對應關系,找到變量i的地址4001,然后從4001開始讀取4個字節數據放到CPU的寄存器中,再找到變量j的地址4005,從4005開始讀取4個字節的數據放到CPU的另一個寄存器中,通過CPU的加法中斷計算出結果。
????在低級語言的匯編語言中都是直接通過地址來訪問內存單元,而在高級語言中才使用變量名訪問內存單元,C語言作為高級語言卻提供了通過地址來訪問內存單元的方法,C++語法也繼承了這一特性。
????由于通過地址能訪問指定的內存存儲單元,可以說地址“指向”該內存單元,例如房間號4001指向系統內存中的一個字節。地址可以形象地稱為指針,意思是通過指針能找到內存單元。一個變量的地址稱為該變量的指針。如果有-一個變量專門用來存放另一個變量的地址,它就是指針變量。在C++語言中有專門用來存放內存單元地址的變量類型,就是指針類型。
????指針是一種數據類型,通常所說的指針就是指針變量,它是一個專門用來存放地址的變量,而變量的指針主要指變量在內存中的地址。變量的地址在編寫代碼時無法獲取,只有在程序運行時才可以得到。
1.指針的聲明
????聲明指針的一般形式如下
數據類型標識符*指針變量名
int *P_iPoint;//聲明一個整數型指針 float *a,*b;//聲明兩個浮點型指針2.指針的賦值
????指針可以在初始化時賦值,也可以在后期賦值。
在初始化時賦值
后期賦值
int i=100; int *a; a=&i;3.關于指針使用的說明
(1)指針變量名是p,而不是*p。
p=&i的意思是取變量i的地址賦給指針變量p。.
下面的實例可以獲取變量的地址,并將獲取的地址值輸出,。
(2)指針變量不可以直接賦值。例如:
int i=100; int *a; a=i;編譯不能通過,有“error C2440: '= : cannot convert from ‘const int’ to 'int '”錯誤提示。
如果強行賦值,使用指針運算符提取指針所指變量時會出錯。例如:
算例:通過指針來比較兩個數的大小
/* 比較兩個數的大小*/ #include <iostream> using namespace std; void main() { int *p1,*p2;//定義兩個指針變量 int *p;//定義一個臨時指針變量 int a,b; cout<<"請輸入一個數:"<<endl; cin>>a; cout<<"請輸入另一個數:"<<endl; cin>>b; p1=&a;p2=&b;//指針賦值 if (a<b) {p=p1; p1=p2; p2=p; } cout<<"較大值:"<<*p1<<endl; cout<<"較小值:"<<*p2<<endl; cout<<"a="<<a<<endl; cout<<"b="<<b<<endl; }4.指針運算符和取地址運算符
????*和&是兩個運算符,*是指針運算符,&是取值運算符。
如圖所示,變量i的值為100, 存儲在內存地址為4009的地方,取地址運算符&使指針變量p得到地址4009。
如圖所示,指針變量存儲的是地址編號4009,指針通過指針運算符可以得到地址4009所對應的數值。.
指針運算符和取地址運算符的說明
聲明并初始化指針變量時同時用到了*和&這兩個運算符。例如:
&p 和&a的區別
&和的運算符優先級別相同,按自右而左的方向結合,因此&p 是先進行運算,p 相當于變量a;再進行&運算,&p 就相當于取變量a的地址。&a 是先計算&運算符,&a就是取變量a的地址;然后進行運算,&a 就相當于取變量a所在地址的值,實際就是變量a。
5.指針運算
????指針變量存儲的是地址值,對指針作運算就等于對地址作運算。下面通過實例來使讀者了解指針的運算。
#include <iostream> using namespace std; void main() { int a=100; int *p=&a;//聲明一個指針變量并初始化 cout<<"p的地址:"<<p<<endl; p--; cout<<"p--的地址:"<<p<<endl; p++; cout<<"p++的地址:"<<p++<<endl;}指針進行一次加 1運算,其地址值并沒有加1,而是增加了4,這和聲明指針的類型有關。p++是對指針作自加運算,相當于語句“p=p+1",地址是按字節存放數據,但指針加1并不代表地址值加1個字節,而是加上指針數據類型所占的字節寬度。要獲取字節寬度需要使用sizeof 關鍵字,
例如整型的字節寬度是sizeof(int), sizeof(int)的值為 4;雙精度整型的字節寬度是sizeof(double),其值為8。將實例中的int指針類型改為double,看看運行結果,代碼如下:
二、指針和數組
1.數組的存儲
數組,作為同名、同類型元素的有序集合,被順序存放在一塊連續的內存中,而且每個元素存儲空間的大小相同。數組中第一個元 素的存儲地址就是整個數組的存儲首地址,該地址放在數組名中。對于一維數組而言,其結構是線性的,所以數組元素按下標值由小到
大的順序依次存放在一塊連續的內存中。 在內存中存儲一維數組如圖所示。對于二維數組而言,用矩陣方式存儲元素,在內存中仍然是線性結構。
2.指針與一維數組
系統需要提供一定 量連續的內存來存儲數組中的各元素,內存都有地址,指針變量就是存放地址的變量,如果把數組的地址賦給指針變量,就可以通過指針變量來引用數組。引用數組元素有兩種方法:下 標法和指針法。通過指針引用數組,就要先聲明一個數組,再聲明一個指針。例如:
int a[10]; int *p;然后通過&運算符獲取數組中元素的地址,再將地址值賦給指針變量。例如:
把a[0]元素的地址賦給指針變量p,即p指向a數組的第0號元素,
通過指針變量獲取數組中的元素
#include <iostream> using namespace std; void main() { int i,a[10]; int *p; //利用循環,分別為10個元素賦值 for(i=0;i<10;i++)a[i]=i; //將數組中的10個元素輸出到設備 p=&a[0]; for(i=0;i<10;i++,p++) cout<<*p<<endl;}如果指針變量p已指向數組中的一個元素,則p+1指向同一數組中的下一個元素。
p+i和a+i是a[i]的地址。a代表首元素的地址,a+i 也是地址,對應數組元素a[i]。
*(p+i) *(a+i)是p+i或a+i所指向的數組元素,即a[i]。
程序中使用指針獲取數組首元素的地址,也可以將數組名賦值給指針,然后通過指針訪問數組。實現代碼如下
#include <iostream> using namespace std; void main() { int i,a[10]; int *p; //利用循環,分別為10個元素賦值 for(i=0;i<10;i++)a[i]=i; //將數組中的10個元素輸出到設備 p=a; for(i=0;i<10;i++,p++) cout<<*p<<endl;}3.指針與二維數組
可以將一維數組的地址賦給指針變量,同樣也可以將二維數組的地址賦給指針變量,因為一維數組的內存地址是連續的,二維數組的內存地址也是連續的,所以可以將二維數組看作是- -維數組。二維數組中各元素的地址如圖7.24所示。
使用指針遍歷二維數組
#include <iostream> using namespace std; void main() {int i,a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};int *p;p=a[0];for(i=0;i<sizeof(a)/sizeof(int);i++,p++){cout<<"地址:";cout<<a[i];cout<<"是";cout<<*p<<endl;} }程序中通過*p對二維數組中的所有元素都進行了引用,如果想對二維數組中某一行中的某一列元素進行引用,就需要將二維數組不同行的首元素地址賦給指針變量。
(1) a+n表示第n行的首地址。
(2) &a[0][0]既可以看作數組0行0列的首地址,也可以看作二維數組的首地址。&a[m][n]就是第m行n列元素的地址。
(3) &a[0]是第0行的首地址,當然&a[n]就是第 n行的首地址。
(4) a[0]+n 表示第0行第n個元素的地址。
(5) *(*(a+n)+m)表示第 n行第m列元素。
(6) *(a[n]+m)表示第n行第m列元素。
4.指針與字符數組
字符數組是一一個一維數組, 使用指針同樣也可以引用字符數組。引用字符數組的指針為字符指針,字符指針就是指向字符型內存空間的指針變量,其一般的定 義語句如下:
char *p;字將數組就是一個字符串, 通過字符指針可以指向一個字符串。 例如,語句
char *p="www.baidu.com";等價于
char *p; p="www.baidu.com";示例:連接兩個字符串
#include <iostream> using namespace std; void main() {char str1[10],str2[5],*p1,*p2;p1=str1;p2=str2;cout<<"請輸入第一個字符串:"<<endl;gets(str1);cout<<"請輸入第二個字符串:"<<endl;gets(str2);while(*p1!='\0')p1++;while(*p2!='\0')*p1++=*p2++;*p1='\0';//添加結束符號cout<<"打印拼接后的字符串";puts(str1); }三、指向函數的指針
指針變量也可以指向一個函數。一個函數在編譯時被分配給一個入口地址,這個函數入口地址就稱為函數的指針。可以用一個指針變量指向函數,然后通過該指針變量調用此函數。一個函數可以返回一個整型值、 字符值、實型值等,也可以返回指針型的數據,即地址。其概念與之前類似,只是返回的值的類型是指針類型而已。返回指針類型的值的函數簡稱為指針函數。
定義指針函數的一般形式為:
類型名*函數名(參數表列);
例如,定義一個具有兩個參數和-一個返回值的函數的指針,其代碼如下:
int *a(int x,int y);
示例:利用指針進行平均值計算
#include <iostream> #include<iomanip>//omanip的作用:主要是對cin,cout之類的一些操縱運算子,比如setfill,setw,setbase,setprecision等等。它是I/O流控制頭文件,就像C里面的格式化輸出一樣. using namespace std; int avg(int a,int b);//函數的聲明 void main() {int iWidth,iLenght,iResult;iWidth=10;iLenght=30;int(*Pfun)(int,int);//定義函數指針Pfun=avg;iResult=(*Pfun)(iWidth,iLenght);cout<<iResult<<endl; }int avg(int a,int b) {return (a+b)/2; }四、引用
引用實際上是一種隱式指針, 它為對象建立一個別名,通過操作符&來實現。&是取地址操作符,通過它可以獲得地址
引用的形式如下:
數據類型&表達式;
例如
int a; int &ia=a;//引用 ia=2;定義了一個引用變量ia,它是變量a的別名,對ia的操作與對a的操作完全一樣。 ia=2 把2賦給a,&ia返回a的地址。執行ia=2和執行a=2等價。
使用引用的說明:
(1)一個C++引用被初始化后,無法使用它再去引用另一個對象,它不能被重新約束。
(2)引用變量只是其他對象的別名,對它的操作與原來對象的操作具有相同作用。
(3)指針變量與引用有兩點主要區別:一是指針是一種數據類型, 而引用不是一個數據類型,指針可以轉換為它所指向變量的數據類型,以便賦值運算符兩邊的類型相匹配;而在使用引用時,系統要求引用和變量的數據類型必須相同,不能進行數據類型轉換。二是指針變量和引用變量都用來指向其他變量,但指針變量使用的語法要復雜- 些;而在定義了引用變量后,其使用方法與普通變量相同。
例如:
引用應該初始化,否則會報錯
如下面算例編譯器會報出“references must be initialized" 這樣的錯誤,造成編譯不能通過。
下面通過一個算例感受下引用
#include <iostream> using namespace std; void main() {int a;int &ref_a=a;//引用a=100;cout<<"a="<<a<<endl;cout<<"ref_a="<<ref_a<<endl;a=2;cout<<"a="<<a<<endl;cout<<"ref_a="<<ref_a<<endl;int b=20;ref_a=b;cout<<"a="<<a<<endl;cout<<"b="<<b<<endl;cout<<"ref_a="<<ref_a<<endl; }1.使用引用傳遞參數
在C++語言中,函數參數的傳遞方式主要有兩種,分別為值傳遞和引用傳遞。所謂值傳遞,是指在函數調用時,將實際參數的值賦值一份傳遞到調用函數中,這樣如果在調用函數中修改了參數的值,其改變不會影響到實際參數的值。而引用傳遞則恰恰相反,如果函數按引用方式傳遞,在調用函數中修改了參數的值,其改變會影響到實際參數。
#include <iostream> using namespace std; swap(int &a,int &b) { int tmp;tmp=a;a=b;b=tmp; }void main() {int x,y;cout<<"請輸入兩個整數x,y:"<<endl;cin>>x;cin>>y;if(x<y){swap(x,y);}cout<<"x="<<x<<endl;cout<<"y="<<y<<endl; }2.使用指針傳遞參數
指針變量可以作為函數參數。使用指針變量傳遞參數和使用引用傳遞參數方式的執行效果相同,可以對同一個函數使用兩種方式傳遞參數進行對比,觀察程序的執行結果。為了使讀者更好地了解指針作為參數進行傳遞的操作,下面通過指針傳遞參數實現變量值的交換功能。
#include <iostream> using namespace std; swap(int *a,int *b) { int tmp;tmp=*a;*a=*b;*b=tmp; }void main() {int x,y;int *ix,*iy;cout<<"請輸入兩個整數x,y:"<<endl;cin>>x;cin>>y;ix=&x;iy=&y;if(x<y){swap(ix,iy);}cout<<"x="<<x<<endl;cout<<"y="<<y<<endl; }3.數組作為函數參數
一、數組名作為函數的參數,傳遞的是一個地址(或常量指針)
#include<stdio.h> void arr(int a[])//數組名作為函數的參數,傳遞的是一個地址(或常量指針) {int i;for(i=0;i<5;i++){printf("%d\n",a[i]);} } int main() {int a[] = {1,2,3,4,5};arr(a);return 0;}}例子:輸出平均值
#include <iostream> using namespace std;int average(int array[10]) {int i, sum = 0;for(i = 0; i < 10; ++i) {sum += array[i];}return sum / 10; }int main() {int i, score[10];cout << "請輸入10個成績:";for (i = 0; i < 10; i++) {cin >> score[i];}cout << "平均成績是:" << average(score) << endl;return 0; }五、指針數組
數組中的元素均為指針變量的數組稱為指針數組,- -維指針數組的定義形式為:
類型名*數組名[數組長度];
例如:int *P[4];
指針數組中的數組名也是一一個指針變量,該指針變量為指向指針的指針。
例如:
int *p[4];
int a=1;
*p[0]=&a;
p是一個指針數組,它的每一個元素是一個指針型數據(其值為地址),指針數組p的第-一個值是變量a的地址。指針數組中的元素可以使用指向指針的指針來引用。例如: .int *(*p);*運算符表示p是一個指針變量,*(*p)表 示指向指針的指針,*運算符的結合性是從右到左,因此“int *(*p);”可寫成“int **p;"。指向指針的指針獲取指針數組中的元素和利用指針獲取- -維數組中 的元素方法相同,如圖所示。
第一次進行指針*運算獲取到的是一個地址值,再進行一次指針*運算,就可以獲取到具體值。
作者:電氣-余登武
總結
以上是生活随笔為你收集整理的C++学习笔记7[指针]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小余学调度:调度禁忌操作讲解(持续更新中
- 下一篇: 西安阔叶黄檀家具哪里好?