簡體   English   中英

GCC 如何處理內置函數

[英]How GCC handles built-in function

我在理解 GCC 內置函數時遇到了麻煩,感到很困惑。

  • 庫函數和內置函數有什么區別?

  • 是否有內置函數可以做而庫函數不能做的事情?

  • 我可以編寫一個庫函數來執行與內置函數 printf 相同的任務嗎? 如何判斷輸入參數的類型(%f、float 或 double)?

  • GCC 內置函數的機器指令不是存儲在庫中的,對嗎? 他們在哪里?

  • 做鏈接的時候,如何控制這些內置功能碼放在哪里?

  • 為什么有時我會在鏈接時出現“未定義對 __builtin_stdarg_start 的引用”之類的錯誤消息

    // main.c #include <stdio.h> int main(void) { printf("hello world!\\n"); return 0; }

    gcc -c main.c, nm 顯示 main.o 中沒有 printf, (only main(T) and puts(U)) ,為什么?

庫函數和內置函數有什么區別?

內置函數是編譯器直接在編譯器內部了解的函數。 庫函數只是在庫中定義的函數。 一個內置函數和一個同名的庫函數可能都存在,所以對於你剩下的問題,我將“庫函數”視為“不是內置函數的庫函數”。

是否有內置函數可以做而庫函數不能做的事情?

是的。 例如,內置函數可以選擇不計算其參數:

int main() {
  int i = 0;
  __builtin_constant_p (++i); // checks whether ++i is a constant expression
                              // does not evaluate ++i
  return i; // returns 0
}

這是因為編譯器可以將內置函數轉換為其他內容,實際上不需要包含任何函數調用。

我可以編寫一個庫函數來執行與函數 printf 中的構建相同的任務嗎?

printf有一些內置知識,但在大多數情況下,這是完全可行的。 查看如何使用<stdarg.h>

如何判斷輸入參數的類型(%f、float 或 double)?

你必須相信調用者讓格式字符串匹配剩余的參數; 當格式字符串需要double時,您無法檢測到諸如傳遞int類的東西。 但是您不需要處理floatdouble之間的區別,因為不可能將float傳遞給printf :它會在printf看到之前轉換為double (無論格式字符串如何)。 printf的要求已經過精心制定,以避免任何編譯器魔術的需要。

GCC 內建函數的機器指令沒有存儲在庫中,對嗎?

對內置函數的調用在編譯時被轉換,但這種轉換可能只是導致對同名庫函數的調用。

他們在哪里?

如果轉換在編譯時完成,則沒有機器指令。 調用被轉換成不同的代碼,然后該代碼被編譯以生成機器指令。 如果結果是對庫函數的調用,則該庫函數的機器指令是庫的一部分。

做鏈接的時候,如何控制這些內建的功能碼放在哪里?

我不明白你在這里的意思。 對內置函數的調用在編譯時轉換為不同的代碼,然后將這些不同的代碼編譯為包含調用的函數的一部分。 它將放置在該包含函數的其余代碼所在的位置。

為什么有時我會在鏈接時出現“未定義對 __builtin_stdarg_start 的引用”之類的錯誤消息

盡管有__builtin前綴,但沒有內置函數__builtin_stdarg_start ,因此這被視為對庫函數的調用。 並且也沒有庫函數__builtin_stdarg_start ,因此鏈接器將其檢測為錯誤。

曾經有一個內置函數__builtin_stdarg_start ,但它在幾年前被刪除了,代碼一開始就不應該使用它。

gcc -c main.c, nm 顯示 main.o 中沒有 printf, (only main(T) and puts(U)) ,為什么?

這是因為printf既作為內置函數又作為庫函數存在。 內置函數通常只是調用庫函數,但有時可以做得更好,包括在您的示例中。 在這種情況下,內置函數printf可以給出正確的結果,而無需調用庫函數printf

大致有兩種內置函數:對應於標准庫函數的函數( mallocprintfstrcpy默認都被視為內置printf ),以及標准庫中沒有對應函數的函數——想想__builtin_expect__builtin_prefetch等。

第一種內置函數使編譯器能夠發出優化的代碼來代替相應的調用。 知道來自標准庫的每個調用的內部語義,編譯器可以決定是發出對駐留在庫中的函數的調用,還是發出自定義生成的代碼片段,以便原始語義被保留並且代碼運行得更好。

第二種內置函數(也稱為“內部函數”)支持使用駐留在庫中的靜態代碼幾乎無法實現的技巧和優化。 它們可能會轉化為向 CPU 提供提示( __builtin_prefetch__builtin_expect ),或通過更好的編譯時內省( __builtin_constant_p__builtin_types_compatible_p )增強 C 語言,或為某些特定於架構的指令( __builtin_ffs__builtin_popcount )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM