2010-02-04 57 views
2

可能重複:
Why #include <stdio.h> is not required to use printf()?printf和scanf工作沒有stdio.h,爲什麼?

兩個printfscanf已經在stdio.h被宣佈。但是他們甚至沒有這個工作,只是拋出一個警告信息?這背後的理論是什麼?

+0

是U使用的是什麼編譯器(事實上,當我關掉libc,我的GNU/Linux系統抱怨沒有_start爲好,而我的OpenBSD系統抱怨_start__guard__stack_smash_handler)。 ? – Amirshk 2010-02-04 11:03:44

+3

@voidmain - 你的名字讓我感到內疚。 – 2010-02-04 11:22:06

+0

Dup:http://stackoverflow.com/questions/336814/why-include-stdio-h-is-not-required-to-use-printf – 2010-02-04 17:14:18

回答

12

調用函數沒有宣佈它將創建基於你給的參數和int假定返回類型的隱式聲明。這使得它可以超越編譯階段,因爲函數可能存在於其他地方,直到鏈接時間才知道 - C並不總是有函數原型,所以這是爲了向後兼容。 (在C++中,這是一個錯誤,而在C99 GCC給出一個警告。)

如果你看一下手冊頁(上FreeBSDDarwin,至少)爲printfscanfputs等,它說,它來自「標準C庫(libc,-lc)」。GCC隱式地與標準C庫鏈接。如果您使用-nostdlib標誌進行鏈接,則會得到您所期望的「未定義符號」錯誤。

+0

C的第一段是正確的,但不是C++,只是說:) – sbk 2010-02-04 12:49:16

1

當你的編譯器警告你,你應該搞清楚這是什麼意思,並解決問題。編譯器警告你關於無效代碼然後繼續編譯代碼的事實意味着很少。

至於爲什麼他們的工作,得到的答覆是「運氣不好」。它似乎只適用於你,但不能保證按照C標準。

+0

他說他得到了警告;顯然他在啓用警告的情況下運行。 – 2010-02-04 11:08:37

+0

@ T.J。 - 不必要。許多編譯器會針對一些常見錯誤無條件地發出警告。然而,提醒警告可以使一些錯誤更清楚,並幫助您更快地抓住它們。 – 2010-02-04 11:21:41

+0

我想我解析錯誤地「放下警告」。不是最好的詞組,但我應該更加小心。謝謝。 – 2010-02-04 11:22:17

6

默認情況下,C編譯器假定沒有聲明返回一個int和不檢查參數的函數功能。它也可以找到一個聲明,那麼編譯器會做參數

+1

我敢肯定,這只是在C,而不是C++。 – Steve314 2010-02-04 11:19:11

+0

是 - 筆記我說過C – Mark 2010-02-04 11:41:57

1

的檢查因爲在C你沒有提供的功能原型,還有的傳遞參數標準轉換,因此,如果您通過同一類型的參數,它應該工作。

回C的早期,其中根本沒有原型,在那裏他們後來添加的。

注意:這在C++中是不同的,在C++中沒有原型的調用函數會導致編譯錯誤。

+0

除了不允許在範圍內沒有原型的情況下調用可變參數函數(如'printf'和'scanf') - 這是未定義的行爲。 – caf 2010-02-04 11:31:23

0

釷GCC編譯器,我懷疑你使用,實際上是「知道」一些如printf的常用功能,並具有特殊的代碼來處理它們。這允許它執行諸如檢查printf的格式字符串之類的事情,這些不是C或C++標準所要求的。

+0

我真的懷疑這是解釋。我很確定如果printf()沒有原型,g ++會拒絕使用printf()。 – asveikau 2010-02-04 11:16:25

+1

gcc會接受它(帶有警告),g ++不會。 GCC確實有特殊的代碼來處理printf - 參見手冊中的-Wformat。 – 2010-02-04 11:18:43

+0

gcc試圖編譯C代碼,而g ++編譯C++。隱式函數聲明(如jleedev描述的)僅在C中合法,而不是在C++中合法。嘗試使用函數int Neil_Butterworth(int)並在*使用後聲明*。在我的編譯器(cygwin,gcc 3.4.4)上有效。那麼,無論是gcc'知道'你,或者它是隱式函數聲明:-) – 2010-02-04 11:44:15

1

在C,如果你不申報的功能,然後你使用它無論如何,默認情況下它返回一個類型int。 (順便說一下,這也是這些函數的返回類型。)另外,在過去的日子裏(ANSI之前),我認爲無論您是否在原型中爲函數指定參數的名稱或類型都沒有關係。所以即使你的情況printf()宣佈爲int printf();你可以傳遞它的參數,它不會抱怨。我不確定標準中是否有這樣的保證,聲明這樣的函數將具有與int (*)(const char *, ...)相同的調用約定,但對於大多數編譯器,我會猜測答案是肯定的。所以它工作。

請注意C++的規則不同。如果您將代碼編譯爲C++,我的猜測是編譯器不會接受它。