C/C++指針介紹與使用詳解
什么是指針
C/C++語(yǔ)言擁有在程序運(yùn)行時(shí)獲得變量的地址和操作地址的能力,這種用來(lái)操作地址的特殊類(lèi)型變量被稱(chēng)作指針。
翻譯翻譯什么tmd叫tmd指針!
變量或常量的指針存儲(chǔ)的數(shù)據(jù)是 :對(duì)應(yīng)的變量或常量在內(nèi)存中的地址。
圖解:
此時(shí) 我們定義三個(gè)指針 p1, p2, p3 分別指向a, b, c ,那么p1中存儲(chǔ)的數(shù)據(jù)是變量a所占用內(nèi)存的首地址:0x00;
b和c中存儲(chǔ)的數(shù)據(jù)是什么呢? 沒(méi)錯(cuò),就是0x02和0x04。
顯然。若要知道變量a的值,首先讀取指針p1中的數(shù)據(jù)0x00,然后讀取內(nèi)存0x00和0x01中的數(shù)據(jù)就可以了。這個(gè)時(shí)候,會(huì)出現(xiàn)一個(gè)問(wèn)題:怎么才能確定究竟要讀取幾個(gè)單位內(nèi)存中的數(shù)據(jù)呢?畢竟p1中只存儲(chǔ)了0x00呀。這個(gè)時(shí)候 ,指針的類(lèi)型就發(fā)揮了作用。舉個(gè)例子:如果定義的指針是int類(lèi)型的,那么讀取的時(shí)候自動(dòng)從指針中存儲(chǔ)的初值向后讀取4個(gè)字節(jié);float類(lèi)型的指針就是讀取8個(gè)字節(jié)。這樣就可以既完整又不多余的取出所需要的數(shù)據(jù)了。
總結(jié)一下一個(gè)指針的兩個(gè)要素:指針類(lèi)型和指針?biāo)缸兞康某醯刂贰?/p>
定義指針變量
指針在定義的時(shí)候最好直接初始化,否則可能出現(xiàn)意想不到的結(jié)果。
@定義一個(gè)指向變量的指針。
/*定義一個(gè)指向int類(lèi)型變量a的指針p*/ int a = 3; int * p; p = &a; //把a(bǔ)的地址賦值給p; /*下面的語(yǔ)句最好不要用?。。?!*/ p = &28; //這也是可以的,p指向的地址中存儲(chǔ)的數(shù)據(jù)是28. /*可以用下面的語(yǔ)句代替上面的語(yǔ)句*/ *p = 28;
間接引用指針
間接引用操作符也是 *
*p 取出p指向的內(nèi)存空間中的值。
所以區(qū)分定義或是引用指針可能有些麻煩。
只有同類(lèi)型的指針和變量才能通過(guò) * 和 & 互相建立關(guān)系。
int a = 0; int temp; int * p = &a; /*指針的間接引用*/ cout<< *p; //輸出結(jié)果是0 /*以下兩種表達(dá)等價(jià)*/ *p = 3; //把3賦值給a a = 3; /*以下兩種表達(dá)效果相同。都是把變量a賦值給temp*/ temp = a; temp = *p; //temp被賦值為0 /* 以下表達(dá)是錯(cuò)誤的*/ float f = 3.1; int * p = &f; //error,指針類(lèi)型與變量類(lèi)型不匹配
常or常常
這個(gè)部分本來(lái)應(yīng)該在定義指針變量里,但是因?yàn)樾枰羔樀拈g接引用作為鋪墊,所以把它單獨(dú)拿出來(lái)了
我們先區(qū)分一組概念:常量、指向常量的指針、常指針以及指向常量的常指針。
1.常量:顧名思義不發(fā)生改變的量,想必大家是熟悉的。
2.指向常量的指針:只限制間接訪(fǎng)問(wèn)操作,不限制指針指向的值本身的操作規(guī)范。
3.常指針:指針中存儲(chǔ)的地址一經(jīng)初始化就不能改變了,也就是說(shuō)常指針只能指向一個(gè)固定的地址,但是地址中存儲(chǔ)的數(shù)據(jù)是可以改變的哦~
4.指向常量的常指針:根據(jù)上面三個(gè)概念大家應(yīng)該可以理解了,就是指針中存儲(chǔ)的地址和該地址中的數(shù)據(jù)皆不可更改。
例如:
int b = 4; const int a = 5; //定義一個(gè)常量a。 /*注意觀(guān)察以下三個(gè)定義中const的位置*/ const int *p = &a; //定義一個(gè)指向常量的指針p,指向常量a。 p = &b; //這個(gè)也是沒(méi)問(wèn)題的哦 *p = 6; //error,這個(gè)間接訪(fǎng)問(wèn)操作是不可以。 int * const p2 = &b;//定義一個(gè)常指針p2 *p2 = 6; //這個(gè)是可以的,注意區(qū)分和上面的區(qū)別 const int * const p3 = &a; //指向常量的常指針p3 /* emm我也不知道該注釋點(diǎn)什么,自行體會(huì)吧~*/ *p = 11; //error,因?yàn)閜指向的是常量,常量的值不可更改 *p2 = 2; //true,p2是常指針,指向的地址不變,但地址中的值可以更改 *p3 = 4; //error p3 = &b; //error
指向指針的指針
指針本質(zhì)上也是一個(gè)變量或常量,那么指針也是有地址的,而指向這些地址的指針被稱(chēng)為指向指針的指針。
int a = 25; int * p = &a; int pp = &p; //true,pp指向的地址中存儲(chǔ)的是指針p的地址。
指針與數(shù)組
一個(gè)數(shù)組的數(shù)組名就是一個(gè)常指針。
int arr[] = {5,4,6,9,8,3};
arr就是一個(gè)指針,而且指向數(shù)組的第一個(gè)元素arr[0]。
指針數(shù)組:
char * arr[] ={"this is", "a", "C++ !"};
在此提及一下字符串常量:
char * a /* 雙引號(hào)的作用: 在字符串結(jié)尾加一個(gè)\0,并分配內(nèi)存空間,返回首地址。 */ a = "dshfw";
指針的運(yùn)算
指針只能支持 + 和 - 的運(yùn)算,但這已經(jīng)足夠滿(mǎn)足大多數(shù)指針操作的需求了。
/*接下來(lái)以數(shù)組為例,只介紹加法 ,減法同理*/ int arr[] = {5,4,6,9,8,3}; cout<< *p; //輸出結(jié)果為5 cout<< *(p+1); //輸出結(jié)果為4 /*打印整個(gè)數(shù)組*/ for(int *p = arr; p < arr+5; ++p) { cout<< *p<<' '; } cout<<endl;
堆內(nèi)存分配
C語(yǔ)言
/*函數(shù)原型*/ void * malloc(size_t size); /*使用:開(kāi)辟5個(gè)int類(lèi)型變量的存儲(chǔ)空間,返回首地址*/ /**/ int *arr; if(arr = (int *) malloc(5 *sizeof(int)) == NULL) { exit(1); } /*釋放堆內(nèi)存*/ free(arr);
C++語(yǔ)言
注意釋放數(shù)組內(nèi)存空間時(shí),delete后有[] !??!
/*申請(qǐng)一個(gè)5個(gè)元素的數(shù)組空間*/ int * arr = new int[5]; delete[] arr; /*申請(qǐng)一個(gè)變量的空間*/ int * arr = new int; delete arr;
指針與函數(shù)
函數(shù)名和數(shù)組名一樣都是一個(gè)指針,有時(shí)我們需要把函數(shù)名作為參數(shù)傳入其他函數(shù)中。
數(shù)組名作為函數(shù)的入口參數(shù)
arr[] = {4,6,9,8,5,3,2,7,5}; /*兩種不同的寫(xiě)法均可以*/ void Sort_Shell(int arr[], int n) { /*code*/ } void Sort_Shell(int * arr, int n) { /*code*/ } /*下面這種是不可以的?。?!*/ void Sort_Shell(int * arr[], int n) { /*code*/ }
舉個(gè)小小的例子
/*來(lái)個(gè)小小的希爾排序算法*/ void Sort_Shell(int arr[], int n) { int gap = n / 2; for(; gap > 0; gap /= 2) { for(int i = gap; i <n; ++i) { int temp = a[i]; int j = i; while(j >= gap&& temp < arr[j - gap]) { a[j] = a[j - gap]; j -=gap; } a[j] = temp; } } }
開(kāi)了個(gè)小差,接下來(lái)回歸正題,我們的指針。
函數(shù)名作為參數(shù)傳入其他函數(shù)
static bool cmp(int a, int b) { return a < b; } void show(bool * b) { if( &b) { cout<< true; } else { cout<<false; } }
使用指針修改函數(shù)參數(shù)
首先來(lái)看個(gè)例子:
void swip(int a, int b) { int c = a; a = b; b = c; } int main() { int a = 5, b = 6; swip(a, b); cout<<a<<' '<<b; }
輸出結(jié)果:5 6
并未達(dá)到交換的效果,因?yàn)楹瘮?shù)內(nèi)部對(duì)形參的修改并不能反映到上層的main函數(shù)中。
此時(shí)我們可以通過(guò)指針作為函數(shù)的入口參數(shù)來(lái)實(shí)現(xiàn)預(yù)期的功能。
void swip(int * a, int* b) { int c = *a; *a = *b; *b = c; } int main() { int a = 5, b = 6; swip(&a, &b); cout<<a<<' '<<b; }
輸出結(jié)果:6 5
傳遞函數(shù)的指針雖然能達(dá)到預(yù)期效果,但是確實(shí)以破壞函數(shù)的黑盒為代價(jià),可讀性差,調(diào)試?yán)щy。
有沒(méi)有什么更好的辦法呢?接下來(lái) 引用登場(chǎng)了。
變量的引用作為函數(shù)的參數(shù)
void swip(int &a, int &b) { int c = a; a = b; b = c; } int main() { int a = 5, b = 6; swip(a, b); cout<<a<<' '<<b; }
輸出結(jié)果:6 5
克服了指針作為參數(shù)的弊端。話(huà)又有點(diǎn)多了,哈哈,這和指針有什么關(guān)系呢······
兩個(gè)常用的字符串函數(shù)
- strcmp() :用于比較字符串的大小。
- strcpy() :復(fù)制字符串。
//函數(shù)原型 int strcmp(const char * arr1, const char * arr2); //使用舉例: char arr1[] = "dfetf"; char arr2[] = "cfefef"; int b = strcmp(arr1, arr2);
輸出b的值是大于0 的。
總結(jié)
指針強(qiáng)大而又危險(xiǎn),卻也是C和C++的靈魂,由于其可以直接操作內(nèi)存地址的特殊性,使得理解指針是如何工作的在C和C++中必不可少,若想成為一名優(yōu)秀的C++工作者,必須要掌握指針。
到此這篇關(guān)于C/C++指針介紹與使用詳解的文章就介紹到這了,更多相關(guān)C++指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c++中queue用法超詳細(xì)講解(入門(mén)必看!)
queue是一種容器轉(zhuǎn)換器模板,調(diào)用#include< queue>即可使用隊(duì)列類(lèi),下面這篇文章主要給大家介紹了關(guān)于c++中queue用法超詳細(xì)講解的相關(guān)資料,需要的朋友可以參考下2022-10-10OpenCV相機(jī)標(biāo)定的全過(guò)程記錄
這篇文章主要給大家介紹了關(guān)于OpenCV相機(jī)標(biāo)定的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-03-03C語(yǔ)言項(xiàng)目爬樓梯的兩種實(shí)現(xiàn)方法參考
今天小編就為大家分享一篇關(guān)于C語(yǔ)言項(xiàng)目爬樓梯的兩種實(shí)現(xiàn)方法參考,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02C語(yǔ)言實(shí)現(xiàn)學(xué)生選修課程系統(tǒng)設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生選修課程系統(tǒng)設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02Qt GUI圖形圖像開(kāi)發(fā)之Qt表格控件QTableView簡(jiǎn)單使用方法及QTableView與QTableWidget區(qū)
這篇文章主要介紹了Qt GUI圖形圖像開(kāi)發(fā)之Qt表格控件QTableView簡(jiǎn)單使用方法,需要的朋友可以參考下2020-03-03C語(yǔ)言實(shí)現(xiàn)二值圖像模擬灰值圖像顯示效果
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)二值圖像模擬灰值圖像顯示效果,分為圖案法、抖動(dòng)法兩個(gè)方法實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10C語(yǔ)言實(shí)現(xiàn)逆序輸出詳細(xì)
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)逆序輸出。主要實(shí)現(xiàn)C語(yǔ)言實(shí)現(xiàn)對(duì)數(shù)組元素依次賦值然后按照逆序輸出,下面文章小編將詳細(xì)解說(shuō),需要的朋友可以參考一下2021-10-10C語(yǔ)言函數(shù)指針數(shù)組實(shí)現(xiàn)計(jì)算器功能
這篇文章主要通過(guò)C語(yǔ)言函數(shù)指針數(shù)組實(shí)現(xiàn)了計(jì)算器的功能,是一個(gè)很好而且流程詳細(xì)的小例子,感興趣的新手朋友們可以自己動(dòng)手也寫(xiě)一遍2022-04-04零基礎(chǔ)學(xué)習(xí)C/C++需要注意的地方
這篇文章主要介紹了零基礎(chǔ)學(xué)習(xí)C/C++需要注意的地方,文中講解非常細(xì)致,供大家參考和學(xué)習(xí),想要學(xué)習(xí)C/C++的可以閱讀此文2020-06-06