[英]Difference between macros and functions in C in relation to instruction memory and speed
根據我的理解,宏和函數之間的區別在於宏調用將被定義中的指令替換,而函數執行整個push,branch和pop -thing。 這是對的,還是我理解錯了?
另外,如果這是正確的,那就意味着,宏會占用更多空間,但會更快(因為缺少推送,分支和彈出指令),不是嗎?
如果C編譯器沒有進行優化,那么您所寫的關於性能影響的內容是正確的。 但優化編譯器可以內聯函數就像它們是宏一樣,因此內聯函數調用以與宏相同的速度運行,並且沒有推/彈開銷。 要觸發內聯,請在編譯器設置中啟用優化(例如gcc -O2
),並將函數作為static inline
函數放到.h
文件中。
請注意,有時內聯/宏更快,有時真正的函數調用更快,具體取決於代碼和編譯器。 如果函數體非常短(並且大部分將被優化掉),通常內聯比函數調用更快。
另一個重要區別是宏可以接受不同類型的參數,並且宏定義可以對多種類型有意義(但編譯器不會為您進行類型檢查,因此如果使用的話,可能會出現不需要的行為或隱藏的錯誤消息宏與錯誤的參數類型)。 這種多態性很難模仿C中的函數(但在C ++中很容易使用函數重載和函數模板)。
這可能是在20世紀80年代,但現代編譯器要好得多。
函數並不總是推送和彈出堆棧,特別是如果它們是葉函數或具有尾調用。 此外,函數通常是內聯的,即使它們是在其他轉換單元中定義的,也可以內聯(這稱為鏈接時優化)。
但你是對的,一般情況下, 當關閉優化時,內聯宏並且不會內聯函數。 兩個版本可能占用更多空間,這取決於宏/功能的細節。
函數以兩種方式使用空間:正文使用空格,函數調用使用空格。 如果函數體非常小,它實際上可以節省空間來內聯它。
是的,你的理解是對的。 但是你還應該注意, 沒有類型檢查宏,它可能導致副作用 。 在括號宏中你也應該非常小心。
你的理解是正確的。 關鍵是在編譯之前解析宏。 您應該將它們視為復雜的文本替換工具(它過於簡單化,但主要是它歸結為它)。
所以不同之處在於,在構建過程中使用了代碼。
這與編譯器在創建最終二進制代碼時對其真正做了什么的問題是正交的 。 或多或少地自由地做任何它認為正確的事情來產生預期的行為。 在C ++中,您只能使用inline
關鍵字來提示您的偏好。 編譯器可以自由地忽略該提示。
同樣,這與整個預處理器業務正交。 畢竟,沒有什么可以阻止你編寫使用inline
關鍵字導致C ++代碼的宏。 同樣,沒有人會阻止你編寫宏,導致很多遞歸的C ++函數,即使你想做,編譯器也可能無法內聯。
結論是你的問題是錯誤的。 這是一個普遍的問題,即具有大量內聯函數的二進制文件與具有大量實函數調用的二進制文件。 宏只是一種技術可以用來影響這種或那種方式的權衡,你會問自己沒有宏的同樣的一般問題。
內聯函數將始終以速度換空間的假設是錯誤的。 內聯錯誤(即太大)功能甚至會對速度產生負面影響。 與這種情況一樣, 不要猜測而是衡量 。
您應該閱讀以下常見問題解答: “內聯函數是否可以提高性能?”
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.