2017-02-17 12 views
2

最近,我嘗試瞭解printf在C中的詳細實現, 我已經理解了va_start,va_arg和va_end, 的用法,但是我總是無法理解的一個問題是printf如何獲取每個參數的大小參數列表雖然知道輸出格式(%d,%c等)。舉一個例子,以更直觀地展現我的問題:C中的printf函數如何獲取變量參數列表中每個參數的大小?

int a = 27; 
char b = 19; 
printf("%d, %c", a, b); 

的詳細printf的,我知道的是,的實現: 第1步:它通過使用宏的va_start(參數得到指針變量參數的開始,格式)是指向下面的字符串「%d,%c」的char指針,args是位於堆棧中的變量參數的開始指針;步驟2:通過使用宏va_arg(args,int)獲取每個參數的值,然後根據格式字符串輸出參數;步驟3:使用va_end(args),清除args指針;

我不明白的關鍵點是,當函數想要輸出a的值時,爲什麼它可以知道使用「int」作爲宏的第二個參數va_arg?宏va_arg的詳細實現是根據指向堆棧的args指針獲取數據,獲取數據的長度取決於第二個參數,這裏是int,爲什麼它將「int」注入到va_arg而不是「char」或「long int」,什麼條件讓它知道注入「int」? 條件是格式字符串? 在上面的例子中,它不能得到a的大小,只能依賴於「%d」。

非常感謝您提前解釋。

+0

您是否知道C的默認參數促銷的概念?我想,這是謎題中缺少的一部分。關鍵是很難將'char'傳遞給你在代碼中顯示的函數。 – unwind

回答

2

...輸出a的值,爲什麼它可以知道使用「int」作爲宏的第二個參數va_arg?

因爲你這麼告訴過它。

%d轉換需要int作爲輸入,所以printf假定您傳遞正確的類型。

如果你得到這個錯誤(即,你通過一個字符%d轉換說明符),它會中斷,這是你的錯。

從我的本地手冊頁中的有關內容:

的參數必須正確(後類型提升)與轉換說明相對應。

this reference有一個詳細的表格,描述了每個轉換說明符所需的參數類型。一些編譯器或靜態分析器可以警告你,如果你的參數類型不符合你的格式字符串,但最終你的責任是正確編碼。

+0

非常感謝,在你的回答的幫助下,我現在可以理解它。 – Ryan