1. 程式人生 > >C語言:函式宣告與定義的引數不一致問題,後果可能很嚴重哦!!!!!

C語言:函式宣告與定義的引數不一致問題,後果可能很嚴重哦!!!!!

 
具體:
在檔案main.c中
int func ();     //宣告中沒引數
int main(){
        int c = func();            //呼叫時也不傳參,這樣才能編譯通過
        printf("%d\n",c);
        return 0;
}


在檔案func.c中
int func(int a, int b,int c, int d, int e, int f,int g,int h,int i,int j, int k,int l,int m,int n){
        int aa = a;
        int bb= b;                
        int cc =c;
        int dd=d;
        int ee =e;
        int ff=f;
        int gg =g;
        int hh = h;
        int ii = i;
        int jj = j;
        int kk =k;
        int ll =l;
        int mm =m;
        int nn = n;
        a = 0;
        b = 0;
        d=0;
        e = 0;
        f = 0;
        g = 0;
        h = 0;
        i = 0;
        j = 0;
        k = 0;
        l = 0;
        m = 0;
        n = 0;
        return b;
}

執行結果
$ gcc main.c func.c

$ ./a.out

0
Segmentation fault

不要懷疑,這個程式可以編譯,連結通過。

但是執行時出錯,因為func的程式碼破壞了main的棧幀,導致“段錯誤”

有人說,C中引數個數有限制,但是畢竟編譯通過了,說明語法沒錯,也就沒有引數個數限制了

這只是個極端的例子,但是還是值得注意:當宣告與定義的引數不一致時,有可能出錯

1)若不定義aa,bb,cc.....這些區域性變數,不把實參a,b,c......傳給他們的話,程式不會出錯

       通過比較彙編程式碼,發現:

       1)若沒定義int aa = a;.....這些語句,則對實參a,b,c......賦值時,修改的是func()函式的棧幀

        2)若有int aa = a;.....這些語句,則對實參a,b,c......賦值時,修改的是main()函式的棧幀  ,這樣當然會把main的棧幀破壞掉