活用指針,const,函數(shù)指針

一、函數(shù)特殊參數(shù)

  • 數(shù)組做函數(shù)參數(shù)
int sum_arr(char arr[], int n)
{
    //函數(shù)內(nèi)部使用 arr[i]或者*(arr+i)來(lái)操作元素即可
}
//等價(jià)于
int sum_arr(char *arr, int n)
{
    //函數(shù)內(nèi)部使用 arr[i]或者*(arr+i)來(lái)操作元素即可
}

//不要試圖將數(shù)組類型和元素個(gè)數(shù)結(jié)合為一個(gè)形參
int sum_arr(char arr[n])
{  
  //這種形參表示法肯定是錯(cuò)誤的
}

//使用多維(例子是n行4列)數(shù)組作為形參。列數(shù)必須明確指定
int sum_arr(char arr[][4], int n)
{
    //也可以使用 char (*arr)[4] ,但是上面那種表示法更為直觀的看到是個(gè)二維數(shù)組
}

char數(shù)組(或字符串)換成其他類型如int、double數(shù)組,也都一樣。
arr[] 和*arr 都只表示為一個(gè)指針,因此函數(shù)實(shí)參傳入一個(gè)數(shù)組名或者字符串常量就可以(兩者都只表示為首元素的地址),就達(dá)到了給指針指向?qū)嶋H地址的目的。
arr[] 更顯示的告訴我們,形參是一個(gè)數(shù)組,而不是一個(gè)單獨(dú)的元素變量。
*arr 更顯示的告訴我們,形參是一個(gè)指針,不是一個(gè)普通的變量,要給他賦地址值。

注意:將數(shù)組名作為參數(shù),也算是值傳遞,不過(guò)傳遞的值是數(shù)組的首地址。
優(yōu)點(diǎn):可以節(jié)省復(fù)制整個(gè)數(shù)組所需的時(shí)間和內(nèi)存。只是簡(jiǎn)單傳遞地址進(jìn)來(lái)就行。
缺點(diǎn):這樣會(huì)使函數(shù)直接操作原始數(shù)據(jù),增加了原始數(shù)據(jù)被破壞的風(fēng)險(xiǎn)。
==》解決這個(gè)問(wèn)題,比較好的方法就是使用const限定符。當(dāng)然如果就是想直接修改原數(shù)組數(shù)據(jù),那么就直接按上面的方法。

二、用const限制指針的能力

  • 指針和const

const 常用于修飾指針,表示只給這個(gè)指針“只讀”權(quán)限,即只能通過(guò)這個(gè)指針來(lái)讀取指向的內(nèi)存地址中的值,而不能通過(guò)這個(gè)指針來(lái)修改指向的內(nèi)存地址中的該值。

int age = 20;
const int * pt = &age;
//只能說(shuō)明不能通過(guò)pt指針來(lái)修改age變量的值,其他的都不能說(shuō)明。
//比如,*pt = 21; 或者 *pt = *pt + 1;  都是錯(cuò)誤的。也就是說(shuō)(*pt)是常量const。
注意:
1、age變量的值,還是可以通過(guò)其他方式改變的,比如 age = 21; 或者age = age +1;
或者指向另一個(gè)普通指針,再通過(guò)指針修改。這都因?yàn)閍ge不是const限定的。
如果是 const int age = 20; 那么age就不能改了。
2、pt指針,也可以被賦給其他地址值,從而指向其他的地址,比如 pt = &myage;
這是因?yàn)橹徽f(shuō)了(*pt)是const,沒(méi)有說(shuō)pt是const。
如果是  int const * pt = &age;  那就說(shuō)明指針pt是const了,指向的地址只能是age的地址不能改變,
但是注意并沒(méi)有說(shuō)age的值不能修改,所以age的值還是可以通過(guò)*pt來(lái)修改的。

  • 禁止將const變量的地址賦給常規(guī)指針
const int age = 20;
int * pt = &age;  //這是非法操作。
const * pr = &age; //這個(gè)可以有,pr為指向const的指針
  • 函數(shù)形參要傳入數(shù)組時(shí),盡量用const修飾指針
int sum_arr(const char *arr, int n)
{
  //或?qū)?arr 換成 arr[] 也可以。
  //使用const限定符,就不能通過(guò)arr指針對(duì)傳遞過(guò)來(lái)的數(shù)組實(shí)參做修改,而是只讀權(quán)限
}
  • 盡可能的使用const

1、這樣可以避免由于無(wú)意間修改數(shù)據(jù)而導(dǎo)致其他錯(cuò)誤。
2、使用const使得函數(shù)能夠處理const和非const實(shí)參。否則只能接受非const數(shù)據(jù)。

三、函數(shù)指針

  • 獲取函數(shù)的地址

函數(shù)名(不帶括號(hào)和參數(shù))就是函數(shù)的地址,比如getName就是函數(shù)名,
而getName()帶上括號(hào)可能就是一次函數(shù)調(diào)用后的返回值name。用函數(shù)名來(lái)作為另一個(gè)函數(shù)的參數(shù)時(shí),一定要注意不能帶括號(hào)。

  • 聲明一個(gè)函數(shù)指針

先要知道函數(shù)原型,比如 int add(int i, int j); (形參可以只留下類型,有變量值ij也好,更清楚)
然后對(duì)用函數(shù)原型就可以聲明函數(shù)指針: int (*p_func)(int i, int j);
也就是直接將函數(shù)名add 用(*p_func)來(lái)代替即可。
賦值:p_func = add; 這樣就讓函數(shù)指針指向了具體的函數(shù)地址。
注意:必須是函數(shù)指針的聲明中函數(shù)類型以及形參列表完全一致,才能完成賦值。

  • 使用函數(shù)指針來(lái)調(diào)用函數(shù)
//比如有如下函數(shù)原型,表示不同的算法。假設(shè)下面已經(jīng)簡(jiǎn)單實(shí)現(xiàn)了這幾個(gè)函數(shù)定義
int add(int i, int j);  //加法
int subtract(int i, int j);  //減法
int multiply(int i, int j);  //乘法
int divide(int i, int j);  //除法

//聲明一個(gè)函數(shù)指針
int  (*p_func)(int i, int j);

//再寫一個(gè)函數(shù),使用上面的函數(shù)指針作為參數(shù),來(lái)智能使用哪種算法
int result(int x, int y,  int  (*p_func)(int, int) )
{
  printf("result is : %d", p_func(x, y) ); //也可以使用*p_func(x,y),效果一樣
}

//最后main函數(shù)調(diào)用result函數(shù)
int main()
{
  result(2, 3, add);    //返回2+3的結(jié)果5
  result(2, 3, multiply);  //返回2*3的結(jié)果6
  return 0;
}
  • 函數(shù)指針的調(diào)用使用,兩種方法都可以。p_func(x, y) 和(*p_func)(x,y)效果一樣。
    不過(guò)(*p_func)(x,y) 給人的直觀感受更強(qiáng),一看就知道這是一個(gè)函數(shù)指針,設(shè)計(jì)的時(shí)候可以更靈活使用它。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容