2014-11-04 68 views
2

我想知道的是編譯器和程序是如何工作的。'printf'原理

例如,在'你好,世界!'例如有,比方說,hello.c中,它是這樣的大家都知道: (使用GNU GCC)

$ gcc -o hello hello.c 
$ ./hello 

世界,你好!

我剛剛得到了一個問題,如何定義或使用printf,最簡單和熟悉的函數之一。

要自己找到答案,我發現整個頭文件包含在stdio.h中,幷包含在包含的頭文件中,包含在包含的頭文件中。 stdio.h中包含幾乎80個頭文件。我查找每個文件是否包含「printf」這個詞。有3個頭文件。

stdio.h中(本身)

位/ stdio2.h

位/標準輸入輸出,ldbl.h

我不知道預處理器語法完全,但我相當肯定這些文件中的文本不足以定義printf函數。例如,在stdio.h,printf的大致指這樣的:

... 
namespace std{ 
... 
extern int printf (const char *__restrict__format, ...); 
... 
} 
... 

我知道它說的語法和種類的聲明,但我認爲這不是一個定義或printf建設。

所以我覺得有一些內心深處可以回答我的問題,我希望你們中的一些人有一個。

+1

我在這裏沒有看到任何問題。你問問定義在哪裏?它在一個圖書館裏,你可能有也可能沒有它的來源;你可以在[這裏]看到它(https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=stdio-common/printf.c)。 – 2014-11-04 14:14:05

+4

如果你正在尋找'printf'的源代碼,你的問題是這個問題的重複:http://stackoverflow.com/questions/4867229/code-for-printf-function-in-c否則我不是當然,我明白你到底在找什麼。 printf的「主體」(原則?)?你是什​​麼意思? – jogojapan 2014-11-04 14:16:20

回答

0

讓我們限制爲C99(不是C++)。

printfvariadic function。你可以用stdarg(3)定義你自己的可變參數函數。

printf也是託管C99中的標準函數。當你有一個#include<stdio.h>編譯器被允許特別優化它。而GCC正在這樣做。請參閱this answer

順便說一句,C標準還定義了vprintf(3)

最後,存在free softwarestandard libc的實現。值得注意的是GNU glibcmusl-libc。你可以學習他們實施printf(用於MUSL-libc中:看到文件src/stdio/printf.c然後src/stdio/vfprintf.c

你可以學習生成的彙編代碼hello.s(看看裏面的一些編輯或尋呼機)由

gcc -Wall -O -fverbose-asm -S hello.c 
獲得
5

你是對的,在頭文件中找到的聲明只是一個前向聲明。

這包含函數簽名,這是編譯器調用該函數所需的所有內容。調用約定,每個參數的類型(以便它可以對該類型執行隱式轉換)等。

實際定義根本不涉及編譯過程。相反,它由C標準庫提供,稱爲libc.a或msvcrt.lib。鏈接器負責確保代碼中的函數調用,編譯器將其轉換爲CALL指令,並使用庫函數實現的正確地址。

要查看實現的源代碼,您需要找出正在使用的運行時庫並下載其源代碼。付費版本的Visual C++附帶CRT源代碼,這也是Windows的gcc編譯器的mingw版本所使用的運行時。在Linux上,您需要下載glibc源代碼。對於cygwin,請查看newlib。嵌入式設備通常使用uclibc對於一些特殊的環境,C庫可能是封閉源代碼,儘管這可能會妨礙調試,所以即使許可證是限制性的,大部分時間源代碼都是可用的。

0

頭文件通常包含函數聲明,而不是定義。該函數的定義將放置在您plarform的標準C庫[例如,linux的glibc]中。你必須下載並分析源代碼。

請參考內核代碼[3.17]中arch/x86/boot/printf.cprintf的源代碼。以獲得printf()的實現邏輯背後的想法。

+1

很確定他沒有使用內核版本,而是libc版本。 – 2014-11-04 14:15:45

+0

當然,這不是非內核程序使用的定義。 – 2014-11-04 14:15:47

+0

@BenVoigt正在編輯我的答案。謝謝。 – 2014-11-04 14:18:03