C語言指針超詳細(xì)講解下篇
前言
本文接著上一篇內(nèi)容,繼續(xù)學(xué)習(xí)指針相關(guān)知識點(diǎn)。
指針運(yùn)算
- 指針±整數(shù)
- 指針-指針
- 指針的關(guān)系運(yùn)算
指針±整數(shù)
#define VALUE 5 int main() { float values[VALUE]; float *vp; //指針+-指針,關(guān)系運(yùn)算 for (vp = &values[0]; vp < &values[VALUE];) { *vp++ = 0;//通過這樣完成初始化 } for (int i = 0; i < VALUE; i++) { printf("%d ", values[i]); } return 0; }
指針-指針
int main() { int arr[10] = { 0 }; printf("%d\n", &arr[9] - &arr[0]);//得到元素的個數(shù) printf("%d\n", sizeof(arr)/sizeof(arr[0]));//計(jì)算元素個數(shù) int* p0 = &arr[0]; int* p9 = &arr[9]; printf("%d\n", (p9 - p0));//得到元素的個數(shù) return 0; }
通過數(shù)組首尾元素的地址相減,得出的就是數(shù)組元素的個數(shù),
-int*表示指針指向的地址里面,存放的數(shù)據(jù)類型是整形,占用4個字節(jié)
- 數(shù)組元素地址+1,就是尋找下一個元素的地址,就會移動4個字節(jié)
通過調(diào)試更加清楚的觀察到這一現(xiàn)象,int 數(shù)組每個元素占用四個字節(jié):
- &arr[0]: 0x005cf7f8
- &arr[0]+1: 0x005cf7fc,地址移動1位,即int*指針移動1位,字節(jié)增加4個。
前提條件:兩個指針必須指向同一塊空間:
char ch[5]; int arr[6]; %arr[4]-&ch[3];//錯誤的
前面的文章介紹了字符串長度的方法兩種方法:
- 循環(huán)
- 遞歸
這里介紹第三種方法, 指針
int mylen(char* pa)//傳參是數(shù)組首元素的地址 { char* p = pa;//首元素地址 while (*pa)//元素不是‘0' { pa++;//通過地址訪問字符串 } //結(jié)尾字符0的地址減首元素地址 return pa - p;//指針相減是元素的個數(shù) } int main() { char arr[] = "abcdef"; int len = mylen(arr); printf("%d", len); return 0; }
指針的關(guān)系運(yùn)算
標(biāo)準(zhǔn)規(guī)定:允許指向數(shù)組元素的指針與指向數(shù)組最后一個元素后面的那個內(nèi)存位置的指針比較,但是不允許與
指向第一個元素之前的那個內(nèi)存位置的指針進(jìn)行比較
int main() { // for (vp = &values[5]; vp > &values[0];) { *--vp = 0; } for (vp = &values[5-1]; vp >= &values[0];vp--)//不允許 //地址會指向首元素前面的地址,這是不允許的 { *vp = 0; } return 0; }
指針和數(shù)組
int main() { int arr[10] = {1,2,3,4,5,6,7,8,9,0}; printf("%p\n", arr); printf("%p\n", &arr[0]); int *p = arr;//p存放的是數(shù)組首元素的地址 return 0; }
數(shù)組名和數(shù)組首元素的地址是一樣的。數(shù)組名表示的是數(shù)組首元素的地址。(2種情況除外,數(shù)組系列文章詳細(xì)介紹了)
既然可以把數(shù)組名當(dāng)成地址存放到一個指針中,我們使用指針來訪問一個就成為可能
int main() { int arr[] = {1,2,3,4,5,6,7,8,9,0}; int *p = arr; //指針存放數(shù)組首元素的地址 int sz = sizeof(arr)/sizeof(arr[0]); for(int i=0; i<sz; i++) { printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p+i); } return 0; }
觀察上圖,所以 p+i 其實(shí)計(jì)算的是數(shù)組 arr 下標(biāo)為 i 元素的地址。那就可以直接通過指針來訪問數(shù)組:
int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = arr; int sz = sizeof(arr) / sizeof(arr[0]); for (int i = 0; i < sz; i++) { printf("%d ",*(p + i)); } printf("\n"); for (int i = 0; i < sz; i++) { printf("%d ", *(p++)); } printf("\n"); for (int i = 0; i < sz; i++) { printf("%d ", arr[i]); } return 0; }
二級指針
指針變量也是變量,是變量就有地址,那指針變量的地址存放在哪里?這就是 二級指針
int main() { int a = 10; int* pa = &a; int** ppa = &pa; return 0; }
- a的地址存放在指針pa中,pa是一級指針
- pa的地址存放在ppa中,ppa是二級指針
對于二級指針的運(yùn)算有:
*ppa 通過對ppa中的地址進(jìn)行解引用,這樣找到的是 pa , *ppa 其實(shí)訪問的就是 pa .
int b = 20; *ppa = &b;//等價于 pa = &b;
**ppa 先通過 *ppa 找到 pa ,然后對 pa 進(jìn)行解引用操作: *pa ,那找到的是 a
**ppa = 30; //等價于*pa = 30; //等價于a = 30;
指針數(shù)組
指針數(shù)組是指針還是數(shù)組?
是數(shù)組。是存放指針的數(shù)組
在數(shù)組系列文章中,已經(jīng)介紹了整形數(shù)組,字符數(shù)組:
int arr1[5];//占用20個字節(jié) char arr2[5];//占用5個字節(jié)
舉例 1
指針數(shù)組:
int main() { int data1[] = { 1,2,3,4,5 }; int data2[] = { 2,3,4,5,6 }; int data3[] = { 3,4,5,6,7 }; //看成二維數(shù)組 int* arr[3] = { data1,data2,data3 }; for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) {//[]是操作符 printf("%d ", arr[i][j]);//不需要解引用 } printf("\n"); } return 0; }
arr3是一個數(shù)組,有五個元素,每個元素是一個整形指針,就是一個地址:
- arr[0],為元素data1,是指針變量,本身也是一維數(shù)組 { 1,2,3,4,5 } 的數(shù)組名,代表首元素地址
- arr[1],為元素data2,是指針變量,本身也是一維數(shù)組 { 2,3,4,5,6 } 的數(shù)組名,代表首元素地址
- arr[2],為元素data3,是指針變量,本身也是一維數(shù)組 { 3,4,5,6,7 } 的數(shù)組名,代表首元素地址
通過調(diào)試也能發(fā)現(xiàn):
- 指針數(shù)組首元素data,是指針變量,也是一維數(shù)組首元素的地址
- 通過數(shù)組名 + i 就能訪問數(shù)組里的元素
- 指針數(shù)組可看成二維數(shù)組
arr[0]=data1;//指針數(shù)組首元素data,是指針變量,也是一維數(shù)組首元素的地址 arr[0][0]=data1[0];//看成一維數(shù)組 arr[0][1]=data1[1]; arr[0][2]=data1[2]; arr[0][3]=data1[3]; arr[0][4]=data1[4];
打印結(jié)果見下圖:
代碼換成下面這個效果一樣,從地址的解引用角度去寫:
int main() { int data1[] = { 1,2,3,4,5 }; int data2[] = { 2,3,4,5,6 }; int data3[] = { 3,4,5,6,7 }; //看成二維數(shù)組 int* arr[3] = { data1,data2,data3 }; for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { printf("%d ", *(arr[i]+j));//地址訪問解引用 } printf("\n"); } return 0; }
舉例 2
指針數(shù)組中元素都是指針變量,就是地址
int main() { int a = 10; int b = 11; int c = 12; int d = 13; int e = 14; int* arr[5] = { &a,&b,&c,&d,&e };//指針數(shù)組存放的元素是指針變量,就是地址 for (int i = 0; i < 5; i++) { printf("%d ", *(arr[i]));//地址解引用 } return 0; }
總結(jié)
本文繼續(xù)學(xué)習(xí)了指針相關(guān)的知識點(diǎn),指針是C語言的重中之重,在基礎(chǔ)階段,指針的學(xué)習(xí)就告一段落了。
下一篇將學(xué)習(xí)結(jié)構(gòu)體的知識點(diǎn)。(鏈接直達(dá))
到此這篇關(guān)于C語言指針超詳細(xì)講解下篇的文章就介紹到這了,更多相關(guān)C語言 指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(27.移除元素)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(27.移除元素),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C++面試八股文之如何實(shí)現(xiàn)strncpy函數(shù)
strncpy函數(shù),主要用做字符串復(fù)制,將于字符從一個位置復(fù)制到另一個位置,那么如何實(shí)現(xiàn)一個strncpy函數(shù),下面小編就來和大家簡單講講吧2023-07-07解讀C語言非void函數(shù)卻沒有return會怎么樣
這篇文章主要介紹了解讀C語言非void函數(shù)卻沒有return會怎么樣的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02