- 后臺(tái)開發(fā):核心技術(shù)與應(yīng)用實(shí)踐
- 徐曉鑫
- 1648字
- 2019-01-03 20:55:32
1.4 指針
1.指針的概念
為了理解什么是指針,必須先弄清楚數(shù)據(jù)在內(nèi)存中是如何存儲(chǔ)的,又是如何讀取的。如果在程序中定義了一個(gè)變量,在編譯時(shí)就給這個(gè)變量分配內(nèi)存單元。系統(tǒng)根據(jù)程序中定義的變量類型,來分配一定長度的空間。例如,C++編譯系統(tǒng)在32位機(jī)器上為整型變量分配4Byte,為單精度浮點(diǎn)型變量分配4Byte,為字符型變量分配1Byte。內(nèi)存區(qū)的每一個(gè)字節(jié)有一個(gè)編號(hào),這個(gè)編號(hào)就是地址,如表1-1所示。
表1-1 用戶數(shù)據(jù)、變量、地址直接的對(duì)應(yīng)關(guān)系

表1-1中展示了用戶數(shù)據(jù)、變量、地址直接的對(duì)應(yīng)關(guān)系。假設(shè)有變量i,存的數(shù)據(jù)是3,那它在內(nèi)存中的地址就是2000。
請(qǐng)務(wù)必弄清楚一個(gè)內(nèi)存單元的地址與內(nèi)存單元的內(nèi)容這兩個(gè)概念的區(qū)別。其實(shí)程序經(jīng)過編譯以后已經(jīng)將變量名轉(zhuǎn)換為變量的地址,對(duì)變量值的存取都是通過地址進(jìn)行的。這種按變量地址存取變量值的方式稱為直接存取方式,或直接訪問方式。還可以采用另一種稱為間接存取(間接訪問)的方式,在程序中定義一種特殊的變量,專門用來存放地址。
由于通過地址能找到所需的變量單元,因此可以說,地址指向該變量單元。因此將地址形象化地稱為“指針”,一個(gè)變量的地址稱為該變量的指針。如果有一個(gè)變量是專門用來存放另一變量地址(即指針)的,則它稱為指針變量。指針變量的值(即指針變量中存放的值)是地址(即指針)。
指針也是一種變量,普通的變量存放的是實(shí)際的數(shù)據(jù),而指針變量包含的是內(nèi)存中的一塊地址,這塊地址指向某個(gè)變量或者函數(shù)。指針的內(nèi)容包括:指針的類型、指針?biāo)赶虻念愋汀⒅羔樀闹狄约爸羔槺旧硭嫉膬?nèi)存區(qū)。例1.6展示了指針的使用。
【例1.6】 指針使用舉例。
#include<iostream> using namespace std; int main(){ int p1=1; // p1是一個(gè)普通的整型變量 int *p2; // p2是一個(gè)指針,指向一個(gè)整型變量 p2=&p1; // 把p1的地址賦值給p2,p2也就指向了p1 cout<<p1<<" "<<*p2<<endl; // *p2就是取p2所指向的地址的內(nèi)容 p1=2; // 那么*p2的值也是2 cout<<p1<<" "<<*p2<<endl; *p2=3; // 那么p1的值也是3 cout<<p1<<" "<<*p2<<endl; return 0; }
程序的執(zhí)行結(jié)果是:
1 1 2 2 3 3
例1.6中定義了一個(gè)整型變量p1,一個(gè)指向整型變量的指針p2,并將p2指向p1。要使用p2指向的內(nèi)容,必須在p2前面加個(gè)*號(hào),也就是*p2。修改了p1的值,*p2的內(nèi)容也會(huì)跟著改變;同樣地,修改*p2的值,p1的值也會(huì)跟著改變。
2.數(shù)組與指針
在C++中,數(shù)組名代表數(shù)組第一個(gè)元素的地址,如下程序定義了兩個(gè)變量:
int *p; int a[10];
若p=a等價(jià)于p=&a[0],可以通過對(duì)p、a的偏移(int類型的指針+1或-1,是向上或向下偏移sizeof(int)個(gè)byte)來訪問數(shù)組里的元素,若用*(p+i)、*(a+i)也可以通過傳統(tǒng)的數(shù)組a[i]訪問各個(gè)元素。
(1)數(shù)組指針,也稱行指針,具體內(nèi)容如下所述。
假設(shè)有定義int(*p)[n];且()優(yōu)先級(jí)高,首先說明p是一個(gè)指針,且指向一個(gè)整型的一維數(shù)組。這個(gè)一維數(shù)組的長度是n,也可以說是p的步長,也就是說執(zhí)行p+1時(shí),p要跨過n個(gè)整型數(shù)據(jù)的長度。如要將二維數(shù)組賦給一指針,應(yīng)這樣賦值:
int a[3][4]; int (*p)[4]; // 該語句是定義一個(gè)數(shù)組指針,指向含4個(gè)元素的一維數(shù)組。 p=a; // 將該二維數(shù)組的首地址賦給p,也就是a[0]或&a[0][0] p++; // 該語句執(zhí)行過后,也就是p=p+1;p跨過行a[0][]指向了行a[1][] // 所以數(shù)組指針也稱指向一維數(shù)組的指針,亦稱行指針。
(2)指針數(shù)組不同于數(shù)組指針,具體內(nèi)容如下所述。
假設(shè)有定義int*p[n];且[]優(yōu)先級(jí)高,可以理解為先與p結(jié)合成為一個(gè)數(shù)組,再由int*說明這是一個(gè)整型指針數(shù)組,它有n個(gè)指針類型的數(shù)組元素。這里若執(zhí)行p+1操作則是錯(cuò)誤的,p=a這樣賦值也是錯(cuò)誤的,因?yàn)閜是個(gè)不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它們分別是指針變量,只用來存放變量地址。但可以這樣*p=a賦值這里*p表示指針數(shù)組第一個(gè)元素的值,a的首地址的值。
如要將二維數(shù)組賦給一指針數(shù)組,程序可以是:
int *p[3]; int a[3][4]; for(i=0;i<3;i++){ p[i]=a[i]; }
這里int*p[3]表示一個(gè)一維數(shù)組內(nèi)存放著3個(gè)指針變量,分別是p[0]、p[1]、p[2],所以要分別賦值。
這樣數(shù)組指針和指針數(shù)組兩者的區(qū)別就很明顯了:數(shù)組指針只是一個(gè)指針變量,可以認(rèn)為是C語言里專門用來指向二維數(shù)組的,它占用內(nèi)存中一個(gè)指針的存儲(chǔ)空間;指針數(shù)組是多個(gè)指針變量,以數(shù)組形式存在內(nèi)存當(dāng)中,占用多個(gè)指針的存儲(chǔ)空間。還需要說明的一點(diǎn)就是,同時(shí)用來指向二維數(shù)組時(shí),其直接引用和用數(shù)組名引用都是一樣的。
比如要表示數(shù)組中第i行j列一個(gè)元素,這幾種方式都可以:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]。
其中,優(yōu)先級(jí):()>[]>*。
3.字符串與指針
字符串是C++中最經(jīng)常用到的操作對(duì)象之一。用字符數(shù)組和字符指針變量都可以實(shí)現(xiàn)字符串的存儲(chǔ)和運(yùn)算。例1.7展示了字符數(shù)組和字符指針是如何使用的。
【例1.7】 字符數(shù)組、字符指針、字符指針數(shù)組、字符串變量應(yīng)用舉例。
#include<iostream> #include<string> using namespace std; int main(){ char str[] = "I am a programmer." ; // str 是一個(gè)字符數(shù)組 char * str1="abc"; // str1是一個(gè)字符指針變量,可以指向一個(gè)字符串 char * str2[]={"hello world","good bye"}; // str2是一個(gè)字符指針數(shù)組,可以存多個(gè)字符串 string str3 = "I am a programmer, too."; // str3是一個(gè)字符串變量 cout<<"str: "<<str<<endl; cout<<"str1: "<<str1<<endl; cout<<"str2[0]: "<<str2[0]<<endl; cout<<"str3: "<<str3<<endl; return 0; }
程序的執(zhí)行結(jié)果是:
str: I am a programmer. str1: abc str2[0]: hello world str3: I am a programmer, too.
例1.7中,str是一個(gè)字符數(shù)組,str1是一個(gè)字符指針變量,str2是一個(gè)字符指針數(shù)組,str3是一個(gè)字符串變量。
(1)字符串指針變量本身是一個(gè)變量,用于存放字符串的首地址。可以改變str1使它指向不同的字符串,但不能改變str1所指的字符串常量。因?yàn)槎x指針時(shí),編譯器并不為指針?biāo)赶虻膶?duì)象分配空間,它只是分配指針本身的空間,所以abc會(huì)被當(dāng)成常量,并且被放到程序的常量區(qū),不能被修改。
(2)字符串本身是存放在以該首地址為首的一塊連續(xù)的內(nèi)存空間中,并以'\0'作為字符串的結(jié)束標(biāo)志。
(3)字符數(shù)組是由于若干個(gè)數(shù)組元素組成的,每個(gè)元素中存放字符串的一個(gè)字符。在定義一個(gè)字符數(shù)組時(shí),編譯后就會(huì)分配一個(gè)內(nèi)存單元,每個(gè)元素都有確定的地址。
4.函數(shù)與指針
函數(shù)指針是指向函數(shù)的指針變量。所以,函數(shù)指針首先是個(gè)指針變量,而且這個(gè)變量指向一個(gè)函數(shù)。C++在編譯時(shí),每一個(gè)函數(shù)都有一個(gè)入口地址,該入口地址就是函數(shù)指針?biāo)赶虻牡刂贰S辛酥赶蚝瘮?shù)的指針變量后,就可以用該指針變量調(diào)用函數(shù)了。
函數(shù)指針的聲明方法是:
返回值類型 (*指針變量名)([形參列表]);
其中,返回值類型說明函數(shù)的返回值類型,(*指針變量名)這句的括號(hào)不能省略。
例如:
int func(int a); // 聲明一個(gè)函數(shù) int (*f) (int a); // 聲明一個(gè)函數(shù)指針 f=&func;
將func函數(shù)的首地址賦值給函數(shù)指針,這里也等價(jià)于f=&func;賦值時(shí)函數(shù)不帶括號(hào),也不帶參數(shù),函數(shù)名就代表了函數(shù)的首地址。例1.8展示了函數(shù)指針調(diào)用函數(shù)的方法。
【例1.8】 函數(shù)指針使用范例。
#include<iostream> using namespace std; int Mmin(int x,int y){ if(x<y)return x; return y; } int Mmax(int x,int y){ if(x>y)return x; return y; } int main(){ int (*f)(int x,int y); int a=10,b=20; f=Mmin; // 把Mmin函數(shù)的入口地址賦給f cout << (*f)(a,b)<<endl; f=Mmax; // 把Mmax函數(shù)的入口地址賦給f cout << (*f)(a,b)<<endl; return 0; }
程序的執(zhí)行結(jié)果是:
10 20
例1.8中定義了一個(gè)函數(shù)指針f,兩個(gè)函數(shù)Mmin和Mmax,先后把f指向Mmin和Mmax函數(shù),執(zhí)行比較兩個(gè)數(shù),分別得出較小值和較大值。
- Microsoft Exchange Server PowerShell Cookbook(Third Edition)
- Learning Apex Programming
- 羅克韋爾ControlLogix系統(tǒng)應(yīng)用技術(shù)
- Programming ArcGIS 10.1 with Python Cookbook
- Python編程完全入門教程
- Java Web基礎(chǔ)與實(shí)例教程
- UVM實(shí)戰(zhàn)
- LabVIEW虛擬儀器入門與測(cè)控應(yīng)用100例
- Django 3.0應(yīng)用開發(fā)詳解
- SQL Server 入門很輕松(微課超值版)
- Python Projects for Kids
- 30天學(xué)通C#項(xiàng)目案例開發(fā)
- Mastering Apache Camel
- 視窗軟件設(shè)計(jì)和開發(fā)自動(dòng)化:可視化D++語言
- Python面向?qū)ο缶幊蹋ǖ?版)