? ? ?OK,這一篇主要是講我學習的3種指針類型。
正文開始:
一.字符指針
? ? 所謂字符指針,顧名思義就是指向字符的指針。一般寫作? " char* "
直接來說說它的使用方法吧:
(1)一般使用情況:
int main()
{char a = 'A';char* p = &a;//取出a的地址printf("%c\n", *p);return 0;
}
打印結果:
(2)特殊使用情況:
int main()
{char s[] = "hello world";const char* p = s;printf("%s\n", p);return 0;
}
先看看運行情況:
這里是創建了一個字符數組寫的字符串,然后用p接收了字符串首字符的地址。? 注意喔,這里不是p接收了整個字符串的地址,這里打印出整個字符串容易讓人誤會是p接收了整個字符串的地址,實際上是因為打印字符串有首元素的地址就可以全部打印了。
驗證一下:
這里就可以看出,這里p和字符串首元素的地址是一模一樣的。
好的,字符指針結束。
?
二.數組指針
? ?我之前還學習過指針數組,剛開始經常把它與數組指針搞混淆,這兩者是完全不一樣的,指針數組是存放指針的數組,而數組指針是指向數組的指針。也就是說,數組指針是指針變量
我們已經熟悉:
? 整形指針變量: int * pint; 存放的是整形變量的地址,能夠指向整形數據的指針。
? 浮點型指針變量: float * pf; 存放浮點型變量的地址,能夠指向浮點型數據的指針。
那數組指針變量應該是:存放的應該是數組的地址,能夠指向數組的指針變量。
? ?
答案是第二個,因為在第一個語句中? []? 的優先級比? ?*? ?更高 ,會優先與p1結合,所以必須用()像(*p2)這樣括在一起。那么p2先和*結合,說明p2是?個指針變量,然后指針指向的是?個??為10個整型的數組。所以p2是 ?個指針,指向?個數組,叫 數組指針。
好的,接下來介紹一下數組指針的用法。
(1)數組指針的初始化:
int main()
{int arr[10] = { 0 };&arr;//取出arr的地址。int (*p)[10] = &arr;return 0;
}
這里就取出了整個數組的地址(&arr)保存到數組指針 p 中
我們調出監視查看:
可以發現arr和p的類型是完全一樣的。
那我們就可以得到下面的結論:
(2)二維數組傳參的本質
?? 知道了數組指針的概念,就可以講一下數組傳參的本質了。
我之前寫二維數組傳參代碼是這樣寫的:
void func(int arr[3][5], int r, int c)
{int i = 0;for (i = 0;i < r;i++){int j = 0;for (j = 0;j < c;j++){printf("%d ", arr[i][j]);}printf("\n");}
}int main()
{int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };func(arr, 3, 5);return 0;
}
可以看到形參接收的時候也是使用(arr[3][5])這樣的二維數組的形式來接受的,那當我學習了數組名是數組首元素的地址和數組指針后我知道了一種新的寫法。
?先我們再次理解?下?維數組,?維數組其實可以看做是每個元素是?維數組的數組,也就是?維數組的每個元素是?個?維數組。那么?維數組的?元素就是第??,是個?維數組
如下圖:
所以,根據數組名是數組?元素的地址這個規則,?維數組的數組名表?的就是第??的地址,是? 維數組的地址。根據上?的例?,第??的?維數組的類型就是 int [5] ,所以第??的地址的類 型就是數組指針類型 int(*)[5] 。那就意味著?維數組傳參本質上也是傳遞了地址,傳遞的是第? ?這個?維數組的地址,那么形參也是可以寫成指針形式的。如下:
void func(int(*p)[5], int r, int c)
{int i = 0;for (i = 0;i < r;i++){int j = 0;for (j = 0;j < c;j++){printf("%d ", *(*(p+i)+j));}printf("\n");}
}int main()
{int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };func(arr, 3, 5);return 0;
}
形參就用數組指針來接收,打印也用解引用地址來打印,
printf("%d ", *(*(p+i)+j));
這一行可能不太好理解,本人也沒那個能耐就用文字說清楚,不懂的朋友可以用AI去解釋,只要熟悉指針了,那還是很好理解的。
好的,數組指針就到這里。
三.函數指針
? ?接下來就是最后的函數指針了。
那么什么是函數指針變量呢? 根據前?學習整型指針,數組指針的時候,我們的類?關系,我們不難得出結論: 函數指針變量應該是?來存放函數地址的,未來通過地址能夠調?函數的。 那么函數是否有地址呢?
很簡單,做個測試就知道了。
測試出來函數果然也是有地址的,并且使用(函數名)和使用(&函數名)打印出來的地址是一樣的,這和數組有點像,但不同的是:? 數組名!= &數組名,但是?函數名==&函數名,也就是說,函數比數組還好記一點。
那么初始化函數指針的方式也就類比著數組的來:
int Add(int x, int y)
{return x + y;
}
int main()
{int(*pf1)(int, int) = Add;
int(*pf2)(int x, int y) = &Add;//x和y寫上或者省略都是可以的return 0;
}
這就把函數(Add)的地址保存到指針變量(pf)中了。
接下來是使用函數指針變量,畢竟初始化了肯定要使用一下的嘛。
int Add(int x, int y)
{return x + y;
}
int main()
{int(*pf3)(int, int) = Add;printf("%d\n", (*pf3)(2, 3));//使用函數指針來調用函數printf("%d\n", pf3(3, 5));//(*pf3)==pf3,不需要使用*符號return 0;
}
注意看我寫在代碼中的注釋,運行結果如下:
這下函數指針的調用也學會了。
四.最后
不知不覺寫了兩個多小時了,學習的時間過得很快,希望現在和未來學的技術都能夠讓我在以后獲得收獲吧。
應該……會的吧,管他呢,反正有問題就解決,人生不就是被問題堆起來的嘛,不出現問題人生反而會有些索然無味吧。
說多了也說偏了,總之謝謝大家的閱讀!