1.可變參函式的原理
c/c++函式的引數是存放在棧區的,並且引數的入棧是從引數的右邊開始,即最後乙個引數先入棧,而第乙個引數最後才入棧,所以,根據棧的後進先出性質,函式總能找到第乙個引數。所以,可變參函式的實現必須能夠從已知引數中獲取到函式所需要引數的個數,否則怎麼知道傳了幾個引數呢。
例如printf函式,第乙個引數就是乙個格式串,而後面所需要的引數個數能夠從格式串中推得。
2.可變參函式的設計
標準標頭檔案提供了一套對可變參函式的實現機制,所以編寫可變參函式需要包含該標頭檔案。
#includec語言的標頭檔案提供了乙個資料型別va_list和三個巨集(va_start、va_arg和va_end),得用它們來實現可變參。va_list是一般是乙個char指標(即字串指標),用來指向可變參的。
來看看這四個玩意一般是怎麼定義的。
typedef char * va_list; //就是個指標呀
#define _intsizeof(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) // 這個有什麼用你得自己看,我管不住你了。可以不看的。#define va_start(ap,v) ( ap = (va_list)_addressof(v) + _intsizeof(v) ) // 將ap指向v之後的位置
#define va_arg(ap,t) ( *(t *)((ap += _intsizeof(t)) - _intsizeof(t)) ) // 取出ap的值,並將ap指向下乙個位置。t就是型別,可以是int,double等等
#define va_end(ap) ( ap = (va_list)0 ) //3.可變長引數函式的實現置空
先上例子,hello world!
例項1::實現求和函式,引數個數可變
1例項2:實現printf的功能int sum(int
n, ...)211
va_end(arg_ptr); //養成習慣
12return
nres;
13 }
1完整例子,g++編過測過了。void myprintf(const
char *strformat, ...)
2; //
小心別溢位?
7 vsprintf(strinfo, strformat, arg_ptr); //
按格式列印到strinfo,功能類似sprintf
8fputs(strinfo, stdout); //輸出
9va_end(arg_ptr);
10 }
1 #include 2 #include 3 #include 4example5int sum(int
n, ...)615
va_end(arg_ptr);
16return
nres;17}
1819
void myprintf(const
char *strformat, ...)
20; //
小心別溢位?
25 vsprintf(strinfo, strformat, arg_ptr); //
按格式列印到strinfo,功能類似sprintf
26fputs(strinfo, stdout);
27va_end(arg_ptr);28}
2930
intmain()
31
(1) va_list的定義即例子見
(2) 各個平台的實現可能是不一樣的,如va_end的實現,故最好先了解你所用的平台。
(3) 實際使用時還有更多的東西要考慮,不僅僅像上面那麼簡單。
十分鐘了解演算法(3) 有趣的演算法
k最近鄰,就是k個最近的鄰居的意思,每個樣本都可以用它最接近的k個鄰居來代表。如果乙個樣本在特徵空間中的k個最相鄰的樣本中的大多數屬於某乙個類別,則該樣本也屬於這個類別,並具有這個類別上樣本的特性。1.特徵抽取 挑選合適的特徵 確定樣本的特徵值,建立n維座標軸 標出每個樣本的點,並使用畢達哥拉斯公式...
一分鐘了解python檔案的open 函式
mode 檔案操作方式 rread 開啟並且讀取檔案內容 預設引數 wwrite 開啟並且向檔案中寫入內容 如果檔案不存在,建立乙個新檔案 每次開啟檔案寫入內容,都會覆蓋原來的內容 at text 開啟乙個文字檔案進行操作 預設引數 bbinray 開啟乙個二進位制檔案進行操作 encoding 檔...
3分鐘秒懂nginx中的location指令
5.匹配問號後的引數 6.location uri結尾帶不帶 7.命名location 8.案例 location指令是nginx中最關鍵的指令之一,location指令的功能是用來匹配不同的url請求,進而對請求做不同的處理和響應,這其中較難理解的是多個location的匹配順序,本文會作為重點來...