多参的实现原理
相信大家都使用過C語言的庫函數:printf("%d%d", 1, 2)的吧,使用確實很方便功能也很強大。
但是為什么它可以接受多個參數呢?
現在我們來解析一下多參的實現原理,網上也找了一些文章。發現解析得都不全面。并且有BUG。
先看如下源碼:
#include <windows.h> #include <stdio.h> #include <winnt.h>void MySprintf(char* szBuffer, const char* szFormat, ...) {va_list pa; // 定義一個指針va_start(pa, szFormat); // 把指針賦值為第一個參數的值vsprintf(szBuffer, szFormat, pa);// va_end(pa); // 清空 } int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) {char szBuffer[128] = {0};MySprintf(szBuffer, "%d%d%d", 1,2,3);return 0 ; }首先,我們函數壓參順序是重右往左,對應的棧空間內存地址從高到低。
MySprintf(szBuffer, "%d%d%d", 1,2,3);
這行代碼,分別想棧中壓入3, 2, 1, 然后再是szFormat的內存空間,在是szBuffer的內存空間.
內存結構如下:
?
熟悉函數調用的幾步過程,壓入參數,保存返回地址和棧頂,開辟局部變量空間.
現在保存了返回地址,然后繼續執行的話,就是保存棧頂和開辟va_list pa所需的內存空間.
va_list其實也就是char* 類型。占4個字節。繼續執行后如下:
看到了嗎,va_start(pa, szFormat); 這條語句計算出了參數的起始地址,
它是如何計算出的呢?我們既然知道了內存布局, 那szFormat取地址+sizeof(va_list)。
說簡單點也就是:szFormat的內存地址 + 4個字節. 不就剛好偏移到第一個參數的地址處了嗎?
并且, 以上的MySprintf函數等同于下面這種寫法:
void MySprintf(char* szBuffer, const char* szFormat, ...) {char* pCh = NULL;pCh = (char*)&szFormat + sizeof(pCh);vsprintf(szBuffer, szFormat, pCh);pCh = NULL; }現在,我們得到了參數的內存首地址,但是還缺少信息。缺什么信息?
當前地址處有幾個參數,每個參數什么類型(占用字節數)?
關鍵的地方就在這里了。szFormat中有類型信息信息,并且有類型信息的個數,我們可以通過遍歷字符串,
找出類型信息的順序和個數。然后根據遍歷找到的信息。來解析參數的內存首地址。
具體的做法.在vsprintf中有實現,下面是拷貝vsprintf的實現代碼,
#ifndef _COUNT_int __cdecl vsprintf (char *string,const char *format,va_list ap) #else /* _COUNT_ */int __cdecl _vsnprintf (char *string,size_t count,const char *format,va_list ap) #endif /* _COUNT_ */{FILE str;REG1 FILE *outfile = &str;REG2 int retval;_ASSERTE(string != NULL);_ASSERTE(format != NULL);outfile->_flag = _IOWRT|_IOSTRG;outfile->_ptr = outfile->_base = string; #ifndef _COUNT_outfile->_cnt = MAXSTR; #else /* _COUNT_ */outfile->_cnt = count; #endif /* _COUNT_ *//*簡單說明:關鍵代碼處,大家直接跟進去即可,先是做些判斷,然后設置一些標志位,最后把數字根據設置的標志轉為字符串.*/retval = _output(outfile,format,ap );_putc_lk('\0',outfile);return(retval); }本人菜鳥,水平有限,望各路大牛指點!
轉載于:https://www.cnblogs.com/ziolo/archive/2013/04/22/3036346.html
總結
- 上一篇: 职业规划之后,还需要什么?职业规划与职业
- 下一篇: 一分六钱用计算机怎么算,交行信用卡分期付