C語(yǔ)言進(jìn)階:指針的進(jìn)階(1)
指針進(jìn)階
我們?cè)诔蹼A時(shí)就已經(jīng)接觸過(guò)指針,了解了指針的相關(guān)內(nèi)容,有:
指針定義:指針變量,用于存放地址。地址唯一對(duì)應(yīng)一塊內(nèi)存空間。
指針大?。汗潭?2位平臺(tái)下占4個(gè)字節(jié),64位8個(gè)字節(jié)。
指針類型:類型決定指針±整數(shù)的步長(zhǎng)及指針解引用時(shí)訪問(wèn)的大小。
指針運(yùn)算:指針解引用,指針±整數(shù),指針-指針,指針關(guān)系運(yùn)算。
本章節(jié)在此基礎(chǔ)上,對(duì)C語(yǔ)言階段指針進(jìn)行更深層次的研究。
字符指針
字符指針,存入字符的地址,類型為char *
字符指針的作用
1.指向單個(gè)字符變量
char ch = 'w'; const char* pch = &ch;
這種很容易理解,就是指針解引用訪問(wèn)字符變量。
2.指向字符串首字符
char* pc = "hello"; printf("%s\n", pc);
這種是把字符串"hello"放進(jìn)指針嘛?
其實(shí)不然,類似于數(shù)組名,該指針存的是常量字符串"hello"的首字符的地址。通過(guò)對(duì)指針解引用訪問(wèn)首字符地址,從而找到整個(gè)字符串。
char* pc = "hello"; printf("%c\n", *(pc + 1));//e printf("%s\n", pc);//hello printf("%s\n", pc + 1);//ello
字符串本質(zhì)上還是在空間上連續(xù)存放,所以指針±整數(shù)同樣有訪問(wèn)的效果。由此也可以看出%s的用法,把地址給%s會(huì)將其后的內(nèi)容看作字符串并打印直到\0 。(所以我猜測(cè)%s的s是string的意思)
字符指針的特點(diǎn)
例題
char str1[] = "hello bit"; char str2[] = "hello bit"; char* str3 = "hello bit"; char* str4 = "hello bit"; if (str1 == str2) printf("str1 = str2\n");//1 else printf("str1 != str2\n");//2 if (str3 == str4) printf("str3 = str4\n");//3 else printf("str3 != str4\n");//4
str1(3)==str2(4),
比較的是二者其實(shí)位置地址是否相同。(地址才是真正判斷二者是否相同的要素)
答案是2和3。因?yàn)?和2是用字符串初始化數(shù)組,3和4是指針指向常量字符串。
str1和str2是普通的數(shù)組,是在內(nèi)存上開辟了兩塊空間不過(guò)存放了一樣的數(shù)據(jù)。
str3和str4指向常量字符串,存放在內(nèi)存的常量區(qū),是不可被修改且具有唯一性即常量區(qū)只存放一個(gè)。所以str3和str4指向的都是同一個(gè)字符串。
常量區(qū)的存儲(chǔ)特點(diǎn):存放在常量區(qū)的數(shù)據(jù)不可被修改,正因?yàn)椴豢尚薷乃源嬉环菥蛪蛄恕:笃谌绻枰?,使用的是同一?shù)據(jù)。(數(shù)據(jù)還是同一個(gè)數(shù)據(jù),只是用不同的指針維護(hù))
小結(jié)
1.常量字符串不可被修改,存放在內(nèi)存的常量區(qū)。
2.具有唯一性即常量區(qū)只存放一個(gè)。
指針數(shù)組
指針數(shù)組的定義
int arr[10];//整型數(shù)組 char ch[5];//字符數(shù)組 float f[20];//浮點(diǎn)型數(shù)組
可見,元素類型也就是數(shù)組的“類型”。
char* pch[5]; int* parr[10]; float* pf[20];
指針數(shù)組就是存放指針的數(shù)組。
int arr[10]; int* arr[10];
整型數(shù)組的數(shù)組名arr
,即首元素地址,是一級(jí)指針。
指針數(shù)組的數(shù)組名parr
,也是首元素地址,不過(guò)其首元素為int*類型變量,所以parr就是二級(jí)指針。
指針數(shù)組的使用
int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 2,3,4,5,6 }; int arr3[] = { 3,4,5,6,7 }; int* parr[] = { arr1,arr2,arr3 }; for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { //1. printf("%d ", parr[i][j]); //2. printf("%d ", *(*(parr + i) + j)); } printf("\n"); }
//答案
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
ps:
parr[i] <==> *(parr+i)
*(parr[i]+j) <==> *(*(parr+i)+j) <==> (*parr+i)[j] <==> parr[i][j]
通過(guò)指針數(shù)組訪問(wèn)整型數(shù)組的每個(gè)元素。parr[i][j]和*(*(parr+i)+j)本質(zhì)上是等價(jià)的。
const char* pch[] = { "abcde", "bcdef", "cdefg" }; for (int i = 0; i < 3; i++) { //1. printf("%s", pch[i]); //2. printf("%s", *(pch + i)); for (int j = 0; j < 5; j++) { //3. printf("%c", pch[i][j]); //4. printf("%c", *(*(pch + i) + j)); } printf("\n"); }
打印字符串使用%s更簡(jiǎn)單,若要使用%c,就是得到每個(gè)字符串的起始地址,分別向后訪問(wèn)。
從這里也可以看出數(shù)組和指針的關(guān)系,我愿稱之為*和[]的愛(ài)恨情仇!
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
VS2022添加代碼模板的實(shí)現(xiàn)步驟(圖文)
使用代碼模板即可實(shí)現(xiàn)像內(nèi)置函數(shù)那樣,只需寫幾個(gè)字母,便能提示自動(dòng)補(bǔ)全,本文主要介紹了VS2022添加代碼模板的實(shí)現(xiàn)步驟,感興趣的可以了解一下2024-06-06詳解MFC/C++調(diào)用易語(yǔ)言的整數(shù)型和文本型與VS2010互動(dòng)
在本篇文章里我們給大家分享了MFC/C++調(diào)用易語(yǔ)言的整數(shù)型和文本型與VS2010互動(dòng)相關(guān)知識(shí)點(diǎn)內(nèi)容,有興趣的朋友們可以參考下。2018-11-11C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易版三子棋游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易版三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07OpenCV中C++函數(shù)imread讀取圖片的問(wèn)題及解決方法
利用C++函數(shù)imread讀取圖片的時(shí)候返回的結(jié)果總是空,而利用C函數(shù)cvLoadImage時(shí)卻能讀取到圖像。怎么回事?今天小編通過(guò)本教程給大家簡(jiǎn)單說(shuō)明原因2017-03-03