什麼情況下需要用局部靜態變量呢?需要保留函數上一次調用結束時的值時,例如可以用下面的方法求n!。
例7.17 輸出1到5的階乘值。
#include <stdio.h>int main( void ){int fac(int n); int i; for(i=1;i<=5;i++) printf("%d!=%d\n" ,i,fac(i) ); return 0;}int fac(int n){static int f=1; f=f*n; return(f);}————譚浩強 ,《C程序設計》(第四版),清華大學出版社, 2010年6月,p207
這段程序的輸出結果是:
1!=1
2!=2
3!=6
4!=24
5!=120
看起來似乎沒有問題,然而稍微仔細思考一下就不難發現,如果若問題再補充一個要求時,比如在求完1到5的階乘後再重新求3的階乘時,那個fac()函數徹底報廢、毫無用處。而造成這種結局的原因則是fac()函數對static莫名其妙的濫用,亦即在不該使用static局部變量時使用了static局部變量。
為了進一步分析這種寫法的荒謬,下面把fac()函數的內容等價地還原到調用者main()函數中,這樣代碼就變成了
view sourceprint?#include <stdio.h>
int main( void )
{
int i;
for ( i = 1 ; i <= 5 ; i++ )
{
static int f = 1 ;
f *= i ;
printf("%d!=%d\n" , i , f );
}
return 0;
}
這段代碼與樣本中代碼在功能上是等效的,但卻沒有樣本代碼的毛病。從這段代碼中不難看出代碼段
view sourceprint?for ( i = 1 ; i <= 5 ; i++ )
{
static int f = 1 ;
f *= i ;
printf("%d!=%d\n" , i , f );
}
是一個有機的功能整體,其中i的取值順序、static局部變量f及求階乘的運算“f *=i”三者之間互相依賴,唇齒相依。
樣本代碼的荒謬則在於把緊密依賴、三位一體的東西變態地閹割出一部分來,並把閹割出的部分寫成了只能一次性使用的“殘疾”函數。由於閹割出的部分包含static局部變量,fac()函數的行為對調用次序具有強烈的依賴性,函數就其本性來說根本不應該具有這種嬌生慣養的依賴性。在大多數情況下,只要函數的調用者提供正確的實參,函數都應該產生正確的副效應和返回值,這才是函數的本分。它與調用者之間只應該存在必要的聯系,所謂“必要”就是不多也不少的參數,除此之外不應該再有什麼別的聯系,這就是所謂的“低耦合”的含義。一旦違背了這個原則,比如樣本代碼那樣閹割不可分的功能,就必然導致變態的強耦合聯系方式。在不滿足這種苛刻的強耦合條件下,函數就會變得毫無用處。這就好比把一個完整的計算機主板掰成兩半,再用膠水粘合在一起,擺擺樣子可以,但主板被分開的任何一部分都已經成了廢品。在函數中濫用static局部變量,最終的效果多半如此。
那麼,是否static局部變量絕對不可以使用呢?倒也不是。但總的來說static局部變量的適應范圍較窄。下面的例子中對static局部變量的使用就非常恰當,無論是把數組name設置為局部還是把它設定為static存儲類別都非常恰到好處。
view sourceprint?#include <stdio.h>
char * month(unsigned) ;
int main( void )
{
puts( month(10) );
return 0;
}
char * month(unsigned m)
{
static char * const name[12]
= {"Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec",};
return name[m-1];
}
摘自:garbageMan