當呼叫函式並且把指向變數的指標作為引數傳入時,通常會假設函式將修改變數(否則,為什麼函式需要指標呢?)。例如,如果在程式中看到語句
f(&x);
大概是希望f
改變x
的值。但是,f
僅需檢查x
的值而不是改變它的值也是可能的。指標可能高效的原因是:如果變數需要大量的儲存空間,那麼傳遞變數的值會浪費時間和空間。
可以使用單詞const
來表明函式不會改變指標引數所指向的物件。const
應放置在形式引數的宣告中,後面緊跟著形式引數的型別說明:
void f(const int *p)
{
*p = 0; // wrong
}
這一用法表明p是指向“常整數”的指標。試圖改變*p
是編譯器會檢查的一種錯誤。
問: 宣告void f(const int *p);
是說函式f
不能修改p
嗎?
答:不是。這說明不能改變指標p
指向的整數物件,但是並不阻止f
改變p
自身。
void f(const int *p)
{
int j;
*p = 0; // wrong
p = &j; // legal
}
因為實際引數是按值傳遞的,所以透過使指標指向其他地方的方法給p
賦新值不會對函式外部產生任何影響。
#include <stdio.h>
void f(const int *p);
int main(void)
{
int i = 6;
int j = 10;
printf("i = %d, j = %d\n", i, j);
f(&j);
printf("i = %d, j = %d\n", i, j);
return 0;
}
void f(const int *p)
{
int j = 33;
p = &j;
}
/* result
i = 6, j = 10
i = 6, j = 10
*/
問:宣告指標型別的形式引數時,像下面這樣在引數名前面放置單詞const
是否合法?
答:是合法的。然而效果不同於把const
放在p
的型別前面。在p
的型別前面放置const
可以保護p
指向的物件。在p
的型別後面放置const
可以保護p
本身:
void f(int * const p);
{
int j;
*p = 0; // legal
p = &j; // wrong
}
這一特性並不經常用到。因為p
很少是另一個指標(呼叫函式時的實際引數)的副本,所以極少有什麼理由保護它。更罕見的一種情況是需要同時保護p
和它所指向的物件,這可以透過在p
的型別前和後都放置const
來實現。
void f(const int * const p)
{
int j;
*p = 0; // wrong
p = &j; //wrong
}