2009-02-23 48 views
2

我跑了下面的代碼,發現了一些奇怪的輸出。K&R和ANSI函數輸出之間的區別

 

int 
mean_ansi (int num1, int num2) 
{ 
    printf ("In %s\n", __FUNCTION__); 
    printf ("num1,num2 is %d,%d\n", num1, num2); 
    return (num1 + num2)/2; 
} 

int 
mean_K_and_R (num1, num2) 
    int num1, num2; 
{ 
    printf ("In %s\n", __FUNCTION__); 
    printf ("num1,num2 is %d,%d\n", num1, num2); 
    return (num1 + num2)/2; 
} 


int 
main() 
{ 
    int i = 6; 
    double f = 1.0; 

    printf ("In %s\n", __FUNCTION__); 
    printf ("[f,i] = [%f,%d]\n", f, i); 

    /* deliberate mistakes */ 
    mean_ansi (f, i); 
    mean_K_and_R (f, i); 

    return 0; 
} 
 

輸出:

在主

[F,I] = [1.000000,6]

在mean_ansi

NUM1,NUM2是1,6-

在mean_K_and_R

num1,num2是0,1072693248

任何人都可以解釋這種行爲。

我看到裝配,但不能發揮出太多。

在這兩種語法中,函數參數在堆棧上的推送方式有什麼不同嗎?

+1

好問題(也是明確填補K&R聲明的最好理由) – 2011-12-04 13:06:17

+0

您可以理智地接受這個問題的答案 - 以及您詢問和收到的很多其他問題的答案。當你想到它時,你可以將此評論標記爲「不再需要」。 – 2017-08-27 07:23:16

回答

2

我做了一些挖掘工作,發現一個thread表明K風格函數聲明不會創建原型,所以如果沒有單獨的原型,編譯器可以自由地根據需要正確處理參數。

我不知道這是多麼的真實,你可以通過快速插入原型並查看函數是否生成相同的值來驗證它。

在任何情況下K & R風格聲明已經過時了,因爲我相信你知道,應該可以避免。如果有什麼問題就是一個例子。

2

我的猜測是,在第一種情況下,有一個隱含的轉換doubleint。在第二個中,代表1.0的64位被解釋爲兩個整數。號碼1072693248表示binnary爲

00111111111100000000000000000000 

,但如果你在this page看一看,你會發現這其實是數字1,第一0爲符號的雙重代表的上半部分,01111111111是指數,其餘的零是分數的高位。只有我沒有得到的是分數爲1的地方?說了這一切,我會預期輸出爲1,1072693248。

+0

小數部分的firt位始終爲1(只要這些值不是低於正常的),即不需要存儲它 – Christoph 2009-02-23 11:19:40

4

丹·奧爾森當時的想法是,和Slartibartfast說明了COM從值:

就好像它是這樣

int mean_K_and_R(); 

即函數定義的mean_K_and_R()定義是治療需要任何參數除了默認參數提升之外,不會進行任何轉換。

如果使用cdecl調用約定,這意味着mean_K_and_R(f, i)將首先推i到堆棧,則f高位比特和然後的f低位。

但該函數認爲它需要兩個整數參數,這意味着num1現在將fnum2的較低位指向f的較高位。

相關問題