1. 程式人生 > >C函式不寫return以及呼叫無參函式時傳參會出現什麼結果

C函式不寫return以及呼叫無參函式時傳參會出現什麼結果

1. 問題描述

  偶然間重新拿起了三年前的C語言,遇到了以前沒有遇到過的問題:
1. C語言中普通函式聲明瞭返回型別但是不用return返回結果,也能夠編譯通過,如下:

#include <stdio.h>

int test1(int a) {
    return 10;
}
int test2(int a) {

}
int main() {
    int a = 1;
    test1(a);
    printf("%d\n", test2(a));//結果為1,如果不是傳入變數而是直接傳入數值,則結果為10
    return 0;
}
  1. 呼叫無參函式時傳入引數,能夠編譯通過,如下:
#include <stdio.h>

int test1() {

}
int main() {
    int a = 1;
    printf("%d\n", test1(a));//1,如果不傳入變數而傳入值,則結果無法理解
    return 0;
}

2. 問題分析

  
  可以肯定的是執行時和使用的暫存器有關
1. 編譯能夠通過,說明gcc編譯器為了效率不會檢查是否有return關鍵字以及無參函式呼叫時是否傳入了引數。
2. 沒有return仍然能夠拿到值,說明和暫存器有關,我們或多或少聽說過eax暫存器,可以通過gdb反彙編檢視究竟。

彙編程式碼太累贅,檢視過程略過,下面直接記錄結論。

3. 結論

  通過檢視函式呼叫的彙編程式碼,可以得出以下結論:

  1. C中函式呼叫的時候的會將實參從右向左依次入棧,這麼做的好處是有利於可變引數實現,呼叫無參函式時可以傳參,但是函式內取不到引數的值。而有參函式必須保證實參和形引數量一致,否則會報引數過多或過少的錯誤。
  2. 如果傳入的引數是變數,則依次放在eax暫存器中,根據上面的入棧順序,就是說eax中儲存的是第一個引數的值;如果傳入的引數是直接量,則不會使用eax暫存器,也就是說上面的test2(a)和test2(1)在傳參的時候,只有前者會將1儲存在eax中。
  3. 使用return關鍵字會將右邊表示式的結果儲存在eax暫存器中,如果不寫return,則eax中可能是之前傳入引數的值,也可能是上一次return的值,看情況分析。

請看下面的例子:

#include <stdio.h>

int test1() {

}
int test2() {

}
int main() {
    int a = 1;
    test1(a);
    printf("%d\n", test2(2));//結果為1
    return 0;
}

兩個test雖然都沒有宣告形參,但是仍然可以傳參,只不過在函式內取不到引數。
呼叫test1,傳入的是個變數,所以此時eax中的值為a的值1,之後呼叫test2,傳入的是個直接量2,不會用到eax,所以eax還是1,由於test2聲明瞭返回型別,但是又不寫return,eax的值還是老樣子,所以整個test2的結果就是eax的值1。

4. 思考

  儘量不要這麼玩,很危險!!!