2012-12-13 117 views
0

對於返回值:未指定的返回值

func() 
{ 
    while(1) 
    { 
    /* do stuff here */ 
    if(error1) exit(0); 
    if(error2) break; 
    }  
    /* no return statement anywhere in func() */ 
} 

但主叫方檢查FUNC()

if(func()) {/* error handling */} 

什麼了不錯的返回碼會有人來確認返回值func()不默認任何東西,並且是垃圾。並認爲這是對所有這些真:

  • void func()
  • int func(),未設有return語句所有,或與普通return;
  • func(),未指定返回類型,我明白默認返回int。

感謝..

+1

另請注意,在沒有列出參數的情況下在C中定義或聲明函數意味着參數也是未指定的。如果函數不需要參數,則必須明確地定義/聲明參數爲「void」。 –

+0

謝謝@JoachimPileborg,我真的在那裏發佈了一些東西來表達我的觀點,但是謝謝。 – nantonop

回答

3

注意:此答案適用於C89(及更早版本)。

void func()指定不返回值的函數。在這種情況下,if (func())應該會導致編譯錯誤。

int func()func()是等價的並返回一個整數值。 如果return語句未提供任何值,則結果未定義,並且如果警告級別足夠高,編譯器會發出警告。 實際上,大多數編譯器會生成代碼,返回用於返回值的寄存器或內存位置中的內容。

+0

-1,隱式int無效C,它已從標準中刪除。 – Lundin

+0

謝謝,就此添加了一個註釋。 –

+1

「結果未定義」 - 準確地說*如果「調用者使用函數調用的值」,行爲*未定義。所以它不只是「可以是任何整數,不知道哪個」,它可能會「崩潰」。不過,我不確定什麼調用約定實際上會導致崩潰。 –

2

一個函數的返回值是通常由處理器的第一寄存器,例如返回基於x86的EAX或基於ARM的r0處理器。它是編譯器特定的,但是或多或少是標準的。

例如在C中的return 10;將被編譯爲

mov eax 10 ; pseudo code 
ret  ; pseudo code 

用於基於x86的處理器的程序集。

&雖然檢查返回值,它只會檢查eax寄存器。無論該寄存器中包含的內容是否被調用者視爲返回值。

SO ...如果你沒有返回值(簡單的return;),或者它是一個void函數,EAX中的ret語句在彙編語言中的任何值都被調用者作爲返回值。

對於基於ARM的處理器,請在上面的答案中將EAX替換爲r0。 :-)

我用這個事實,作爲一個黑客下面的功能;-)

void* getStackTop(){ 
    asm("mov eax esp"); 
} 

要檢查它究竟是如何工作的,而由C翻譯成ASM,下面寫一個簡單的代碼:

int testfn(int unused){ 
    int unused2=unused; // Check how input is passed 
    return 10;   // Check how output is returned 
} 

&然後用gcc -S編譯。 (或與您的編譯器只會生成組件的一些標誌)。


我不知道它是如何返回浮點/結構值。 可能是它返回一個指向struct &的指針,整個返回的結構在引擎蓋下被memcpy化,同時轉化爲asm。有人可能會糾正:-)

+0

您只是描述了許多可能的未定義行爲之一。在這種情況下,這並不是真正相關的,因爲發佈的代碼是無效的。 – Lundin

+0

這個答案與常見的編譯器(如gcc/visual studio等)一致。但是,它在某些編譯器上可能會有所不同。加上許多編譯器,包括gcc _allow_一些增加/放寬到**標準** C.至少在gcc上,它只會給出警告,如果你省略了返回類型並且它會假設'int':'warning:返回類型默認爲int [-Wreturn-type]' – anishsane

+0

但是還有很多其他的CPU架構,你的答案不適用。對於每個這樣的體系結構,都有各種不同的編譯器,具有不同的調用約定。 – Lundin

0

自從C99標準以來,您在無效的C代碼中發佈的代碼。

如果您使用的是一個實現了C90標準的過時編譯器,它將進行編譯,並且默認類型將爲int。我相信從這樣的函數中省略return語句會導致未定義的行爲,儘管我不能引用C90標準。

+0

「一個過時的編譯器」 - 例如gcc。或者用合適的命令行選項鏗鏘聲。或MSVC。這不是編譯器實現的問題,而是編寫代碼的語言。如果它是用C89編寫的,那麼你可能需要一個C89編譯器來編譯它,即使它碰巧也是有效的C99,爲了謹慎起見,編譯C89通常比編譯它在C99中的含義是否更容易與C89中的含義相同。 –