這種技術也會帶來一些新的問題。一般C傳遞數據的值,其緣由是要保護原始數據的完整性。函數使用原始數據的一份拷貝,這樣就不會意外的修改原始數據。可是,因爲處理數組的函數直接操做原始數據,因此它可以修改原數據。有時候這正是咱們須要的,好比給某個數組的全部元素加上同一個值;然而也許其餘函數並不但願修改數據,好比只是計算數組中全部元素的和。數組
10.6.1 對形式參量使用 const函數
在k&RC中,避免此類錯誤唯一的方法就是警戒不出錯。ANSI C中有另外一種方法。spa
若是設計意圖是函數不改變數組的內容,那麼能夠在函數原型和定義的形式參量聲明中使用關鍵字const。例如sum()的原型的定義應該以下:設計
int sum (const int ar[],int n); //原型指針
int sum (const int ar[],int n) //定義code
{ ... }ip
這告知編譯器:函數應當把ar所指向的數組做爲包含常量數據的數組對待。這樣若是你意外的使用諸如ar[i]++之類的表達式,編譯器將會發現這個錯誤並生成一條錯誤消息,通知您函數試圖修改常量。原型
須要理解的是,這樣使用const並不要求原始數據是固定不變的。這只是說明函數在處理數組時,應把數組看成是固定不變的。使用const能夠對數組提供保護,就像按值傳遞能夠對基本類型提供保護同樣,能夠阻止函數修改調用函數中的數據 。編譯器
總之,若是函數想修改數組,那麼在聲明數組參量時就不要使用const;若是函數不須要修改數組,那麼在聲明數組參量時最好使用const。io
請看程序清單10.14中的程序,其中一個函數顯示數組,另外一個函數對數組的每個元素乘上一個給定的數值。由於第一個函數不須要修改數組,因此使用const;由於第二個函數須要修改數組,因此不使用const。
程序清單10.14 atf.c程序
/*arf.c --處理數組的函數*/ #include <stdio.h> #define SIZE 5 void show_array (const double ar[],int n); void mult_array (double ar[],int n,double mult); int main(void) { double dip[SIZE]={20.0,17.66,8.2,15.3,22.22}; printf("The original dip array: \n"); show_array(dip,SIZE); mult_array(dip,SIZE,2.5); printf("The dip array after calling mult_array(): \n"); show_array(dip,SIZE); return 0; } /*顯示數組內容*/ void show_array (const double ar[],int n) { int i; for(i=0;i<n;i++) printf("%8.3f ",ar[i]); putchar('\n'); } /*用同一個乘數去乘每一個數組元素*/ void mult_array (double ar[],int n,double mult) { int i; for(i=0;i<n;i++) ar[i]*=mult; }
輸出結果以下:
The original dip array: 20.000 17.660 8.200 15.300 22.220 The dip array after calling mult_array(): 50.000 44.150 20.500 38.250 55.550
請注意兩個函數都是void類型的。函數mult_array()確實使數組dip獲得了新的值,但不是使用rerutn機制實現的。
10.6.2 有關const的其餘內容
前面咱們講過可使用const來建立符號常量:
const double PI=3.14156;
以上也可使用#define指令實現。但使用const還能夠建立數組常量、指針常量以及指向常量的指針。
指向常量的指針不能用於修改數值,考慮如下代碼:
double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};
const double *pd=retes; //pd指向數組開始處
第二行代碼把pd聲明爲指向const double 的指針。這樣,就不能使用pd來修改它所指向的數值。
*pd = 29.89; //不容許
pd[2] = 222.22; //不容許
rates[0] = 99.99 //容許,由於rates不是常量
不管使用數組符號仍是指針符號,都不能使用pd修改所指向的數據的值。另外須要注意,還可讓pd指向其餘地址:
pd++; /*讓pd指向rates[1] -這是容許的*/
一般把指向常量的指針用做函數參量,以代表函數不會用這個指針來修改數據。例如,程序清單10.14中函數show_array()的原型能夠以下定義:
void show_array(const double *ar,int n);
關於指針賦值和const有一些規則須要注意。
首先,將常量或很是量數據的地址賦給指向常量的指針是合法的:
double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};
const double locked[4]={0.08, 0.075, 0.0725, 0.07};
const double * pc = rates; //合法
pc = locked; //合法
pc = &rates[3]; //合法
然而,只有很是量數據的地址才能夠賦給普通指針:
double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};
const double locked[4]={0.08, 0.075, 0.0725, 0.07};
double * pc = rates; //合法
pc = locked; //非法
pc = &rates[3]; //合法
這樣的規則是合理的。不然,您就可使用指針來修改被認爲是常量的數據。
這些規則的實踐結果是:像show_array()這樣的函數能夠接受普通數組和常量數組的名稱做爲實際參數,由於兩種參數均可以賦給指向常量的指針:
show_array(rares,5); //合法
show_array(locked,4); //合法
可是,像mult_array()這樣的函數不能接受常量數組的名稱做爲參數:
mult_array(rates,5,1.2); //合法
mult_array(locked,4,1.2); //非法
所以,在函數參量定義中使用const,不只能夠修護數據,並且使函數可使用聲明爲const的數組。
const還有不少的用法。例如,您可使用關鍵字const來聲明並初始化指針,以保證指針不會指向別處,關鍵在於const的位置:
double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};
double * const pc = rates; //pc指向數組的開始處
pc = &rates[2]; //不容許
*pc = 92.99; //能夠,更改rates[0]的值
這樣的指針仍然能夠用來修改數據,可是它只能指向最初賦給它的地址。
最後,可使用兩個const來建立指針,這樣的指針即不能夠更改所指向的地址,也不能夠修改所指向的數據:
double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};
const double * const pc = rates;
pc = &rates[2]; //不容許
*pc = 92.99; //不容許