假設我只想要某個標頭中的一個(或幾個)函式,但它是一個我可以定義的函式,其效率與庫的實作相同。我應該包含一個庫頭檔案還是實作我自己的函式?哪個更好?
我正在學習我的第一語言 C,我很喜歡它。
編輯:
你們中的大多數人沒有得到這個問題。忘記可移植性,如果它讓你高興“假設”我可以以完全相同的效率制作一個功能。或者我們只是說我以某種方式得到了相同的實作。
我在某處讀到
#include 指令告訴前處理器打開一個指定的檔案并將其內容插入到當前檔案中。
<stdlib.h> 之類的標頭包含很多東西,所以我想知道是將其所有內容插入檔案,還是插入帶有我想要的自定義標頭,這在速度或記憶體或程式大小方面更有效?
uj5u.com熱心網友回復:
將所選評論(主要是我的)的編輯版本轉移到答案中。
包含標頭 - 標頭作者可能會更改頭檔案中的某些內容,這可能會導致您的代碼出現各種問題。pm100
請注意 C 標準明確指出(第 7.1.4 節庫函式的使用?2):
如果可以在不參考頭檔案中定義的任何型別的情況下宣告庫函式,則也允許宣告函式并在不包括其關聯頭檔案的情況下使用它。
您正在考慮做的事情是允許的(有警告),但這樣做是不明智的。使用標題。
您正在擔心微優化。不!除非您進行編譯的計算機上的芯片速度以兆赫茲或更低的兩位數來衡量,否則您就是在浪費時間來節省微不足道的計算機時間。
- 包括標題。 包括標準標題。
如果您在一個模塊中達到 50 個標頭,那么您可能會開始擔心。你還不在那里。如果標題寫得正確,你仍然不會擊敗包括它們。使用標頭可以保護您免受標頭中宣告的更改。沒有什么比發現沒有包含頭檔案但一些宣告是手寫的,然后函式在頭檔案中更改,但你不知道,因為你沒有使用頭檔案更令人沮喪。這是雙重維護的噩夢——或者如果您在多個檔案中擁有舊版本的函式宣告,則比雙重維護的噩夢還要糟糕。
一般來說,頭檔案只宣告函式和呼叫函式所需的支持資訊(型別、宏)。該函式的實作在一個單獨鏈接的庫中。您使用宣告的標題,以便您可以呼叫函式 - 它們的實作在鏈接和執行程式時加載的庫中。您不會在代碼中獲得函式的副本——當您鏈接程式時,有一個庫提供該函式。因此,包括<stdlib.h>使各種函式可用于呼叫,但不會將它們中的任何一個添加到您的目標檔案中。
除非它有缺陷,否則您不會重新實作庫中的內容。您使用庫,并且要使用庫,您使用標題。標頭包含函式的宣告;該庫包含函式的實作。如果是標準 C 庫代碼、POSIX 庫代碼或 O/S 額外函式,您將在運行時加載共享庫。如果您使用靜態鏈接,則這些函式將鏈接到您的可執行檔案中。無論哪種方式,你都不用擔心——在你學習的時候不用擔心,通常以后也不會。
您正在擔心微優化。你不應該擔心微優化。很長時間沒有。
您似乎想要一個答案,即“不要包含標題,因為其中的所有垃圾都會使您的程式變得比必要的更大”。這不是一個正確的答案,因為包含標題不會使您的程式超出必要的范圍。
- 標頭僅包含宣告,而不包含定義。
- 宣告不會占用可執行檔案中的空間(盡管它們會占用編譯器中的一些空間)。
- 定義確實在您的可執行檔案中占用空間。
如果您的系統在運行時使用共享庫,則整個共享庫將在記憶體中。但是,所有使用相同共享庫的行程都將使用相同的記憶體來存盤代碼(但每個行程都有自己的任何可修改資料的副本),因此記憶體空間是凈勝出的。
靜態鏈接改變了空間方程。靜態鏈接的程式將包含它使用的函式,以及這些函式使用的函式,但不會包含它不需要的任何內容。這將與任何其他程式使用的代碼分開,因此如果您運行多個靜態鏈接的程式,每個程式將在記憶體中擁有自己的映像,包括它自己的任何庫函式的副本。如果您有自己的任何函式的實作鏈接到您的程式,這些將占用每個程式單獨的記憶體,因為它們是靜態鏈接的。
而且,如果您的程式使用任何共享庫,它們仍將加載到系統上,因此您未使用的共享庫中的函式將會產生開銷。
這不是便攜性的問題。這不是替換函式的運行時效率問題。這是一個理智和基本良好軟體工程的問題。您沒有充分的理由重新創建代碼。而且(關鍵點),包括標題不會使您的程式增長。
(注意:C 確實有帶有模板的“僅標頭”庫——Boost 庫是一個主要示例。包含此類標頭意味著您的代碼呼叫的函式可以使用標頭中的資訊進行實體化。聯結器通常會設法避免通過消除實體化函式的重復副本會產生過多的開銷。因此,由于包含頭檔案,您仍然不必擔心程式增長。僅頭檔案的庫在 C 中很少見。)
uj5u.com熱心網友回復:
歡迎來到 Stack Overflow。首先讓我說你所問的一般不會發生。通常創建庫是為了防止重寫大量代碼。但是,如果確實發生了,首先要考慮的是可移植性。
雖然它并不完全準確,但我們可以假設部署的軟體比您撰寫的程式更有可能得到維護。如果需要對該軟體進行更改,您最終將在更新系統并重新編譯后引入該更改。
另一方面,如果您確定,即使某些事情發生了變化,您也不希望它發生變化,那么請務必自己實施。假設您的代碼與庫一樣高效,則不會有性能差異。
uj5u.com熱心網友回復:
我認為在你學習的程序中,你應該按順序做以下兩件事:
- 實施和測驗您的自創功能
- 查看庫函式與您的實作有何不同
庫函式并不總是“最佳”解決方案:它們通常是最好的,但不一定是最有效的。
盡管我在作業中幾乎完全依賴庫,但像許多程式員一樣,我開始使用許多標準庫函式的本地(和錯誤)等效項。撰寫該代碼幫助我成為一名更好的程式員。
uj5u.com熱心網友回復:
是的,使用已經撰寫好的并且可能經過更好測驗的版本。
我可以以與庫的實作相同的效率進行定義
你誤會了。我不在乎您是 Kernighan 還是 Ritchie 或其他人,您撰寫的代碼甚至不會達到編譯器標準庫優化的一半。您將遇到需要修復的錯誤,因此當出現崩潰時您將永遠無法信任您的標準庫,因此您也必須始終對其進行除錯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/459272.html
