print.h
[cpp]view plain
copy
?
#ifndef __print_h_
#define __print_h_
voidprint(char* fmt, ...);
voidprintch(charch);
voidprintdec(intdec);
voidprintflt(doubleflt);
voidprintbin(intbin);
voidprinthex(inthex);
voidprintstr(char* str);
#define console_print(ch) putchar(ch)
#endif /*#ifndef __print_h_*/
上面print函式為全功能的列印函式,可以實現類似printf的功能,printch實現單個字元的列印、printdec實現十進位制格式數字的列印,printflt實現浮點數的列印,printbin實現二進位制格式數字的列印,printhex實現十六進製制格式數字的列印,printstr實現字串的列印,console_print函式是串列埠單字元列印函式的巨集定義,這裡暫時用pc終端單字元列印函式putchar代替。在實際嵌入式環境下,替換成串列埠單字元列印函式即可。
print.c
[cpp]view plain
copy
?
#include
#include
#include "print.h"
intmain(void)
voidprint(char* fmt, ...)
pfmt++;
}else
} va_end(vp);
}voidprintch(charch)
voidprintdec(intdec)
printdec(dec/10);
printch( (char)(dec%10 + '0'
));
}voidprintflt(doubleflt)
voidprintstr(char* str)
} voidprintbin(intbin)
printbin(bin/2);
printch( (char)(bin%2 + '0'
));
}voidprinthex(inthex)
printhex(hex/16);
if(hex < 10)
else
} 編譯執行結果如下:
[cpp]view plain
copy
?
print: c
print: 1234567
print: 1234567.123456
print: string test
print: 0b1001000110100010111111111
print: 0xabcdef
print: %
如上所示,print函式實現了類似printf的功能。
總結:
1、函式引數的傳遞原理
函式引數是以資料結構:棧的形式訪問,從右至左入棧,因此棧底高位址,棧頂低位址,舉個例子如下:
void func(int x, float y, char z);
那麼,呼叫函式的時候,實參 char z 先進棧,然後是 float y,最後是 int x,因此在記憶體中變數的存放次序是 x->y->z,因此,從理論上說,我們只要探測到任意乙個變數的位址,並且知道其他變數的型別,通過指標移位運算,則總可以順藤摸瓜找到其他的輸入變數。
2、下面是 裡面重要的幾個巨集定義如下:
typedef char* va_list;
void va_start ( va_list ap, prev_param ); /* ansi version */
type va_arg ( va_list ap, type );
void va_end ( va_list ap );
實現步驟:
a、va_list 是乙個字元指標,可以理解為指向當前引數的乙個指標,取參必須通過這個指標進行。
在呼叫參數列之前,定義乙個 va_list 型別的變數,(假設va_list 型別變數被定義為ap);
b、然後應該對ap 進行初始化,讓它指向可變參數列裡面的第乙個引數,這是通過 va_start 來實現的,第乙個引數是ap 本身,第二個引數是在變參表前面緊挨著的乙個變數,即「...」之前的那個引數;
c、接著呼叫va_arg,它的第乙個引數是ap,第二個引數是要獲取的引數的指定型別,然後返回這個指定型別的值,並且把 ap 的位置指向變參表的下乙個變數位置。
d、 獲取所有的引數之後,我們有必要將這個 ap 指標關掉,以免發生危險,方法是呼叫 va_end,他是輸入的引數 ap 置為 null。
printf可變引數原理
當呼叫printf時引數的個數是不限定的,那麼該函式是如何實現的呢?來看一下該函式的定義 int printf const char format,argument printf的第乙個引數就是那個字元指標即為被雙引號括起來的那一部分,函式通過判斷字串裡控制引數的個數 d等等 來判斷引數個數及資料型...
printf 可變引數封裝
define fb fmt,fa fmt,va args va args 就只是告訴編譯器,fa可以接受可變引數,不要報錯,相當於又把 傳遞下去了 兩個 的解釋請參見宋寶華 linux裝置驅動程式開發詳解 4.0核心 p80 void fa fmt,typedef char va list va l...
printf談可變引數函式的實現
一直以來都覺得printf似乎是c語言庫中功能最強大的函式之一,不僅因為它能格式化輸出,更在於它的引數個數沒有限制,要幾個就給幾個,來者不拒。printf這種對引數個數和引數型別的強大適應性,讓人產生了對它進行探索的濃厚興趣。關鍵字 printf,可變引數 1.使用情形 int a 10 doubl...