2010-11-23 25 views
12

假設你有一個C代碼是這樣的:C函數定義爲int,但其在體內無return語句仍然編譯

#include <stdio.h> 

int main(){ 
    printf("Hello, world!\n"); 
    printf("%d\n", f());  
} 

int f(){ 

} 

它編譯罰款與海灣合作委員會,並輸出(我的系統上)是:

你好,世界!

但是..但是..這怎麼可能?我認爲C不會讓你編譯這樣的東西,因爲f()沒有返回整數的返回語句。爲什麼允許?它是C特性還是編譯器遺漏,以及從哪裏來的?

+0

爲什麼它不讓f()返回,但不是主要() – Falmarri 2010-11-23 19:42:24

+0

是的,這是很好的觀點:) – Nikita 2010-11-23 19:49:35

回答

15

在這種情況下,根據確切的平臺,返回值很可能是彙編級返回寄存器中發生的任何隨機值(例如x86上的EAX)。不顯式返回一個值是允許的,但給出一個未定義的值。

在這種情況下,14是從printf返回的值。

1

函數的默認返回值是int。換句話說, 除非明確指定 默認返回值,編譯器會將 作爲函數的整數值。

因此,允許省略return語句,但如果您嘗試使用它,則會返回未定義的值。

1

您的編譯器設置的警告級別可能很低。因此,即使結果未定義,也是允許的。

8

使用-Wall進行編譯,以便在編譯器中進行更多的智能檢查。

gcc -Wall /tmp/a.c 
/tmp/a.c: In function ‘main’: 
/tmp/a.c:5: warning: implicit declaration of function ‘f’ 
/tmp/a.c:6: warning: control reaches end of non-void function 
/tmp/a.c: In function ‘f’: 
/tmp/a.c:10: warning: control reaches end of non-void function 

注意它是如何標記缺失的返回語句 - 「控制達到非void函數的結束」?

總是使用-Wall或類似的編譯 - 你將爲以後節省自己的心痛。


我記得好幾次,當這個確切的問題已經引起了數小時或調試的天才修好 - 它八九不離十工作,直到它不是做一天。

0

我編譯-Werror=return-type以防止這種情況。如果你不從函數返回,GCC會給出一個錯誤(除非它是無效的返回)。

4

14正好也是第一個printf的返回值。很可能,編譯器優化了對f()的調用,然後在EAX上剩下14個。

嘗試使用不同的優化級別(-O0,-O1,-O2,-O3,-Os)編譯代碼並查看輸出是否更改。

2

18是第一個打印語句的返回值。(打印的字符數)

該值存儲在堆棧內存中。

在第二個printf函數中,堆棧值由函數f'返回'。但是f只是將printf在該堆棧中創建的值留下。

例如,在這個代碼:

#include <stdio.h> 

int main(){ 
    printf("Hello, world!1234\n"); 
    printf("%d\n", f());  
} 

int f(){ 

} 

哪個編譯罰款與海灣合作委員會,並輸出(我的系統上)是:

你好,世界!

返回值寄給我的printf()細節。

相關問題