printf可變引數實現

2021-06-05 11:39:32 字數 3194 閱讀 4099

print.h

[cpp]view plain

copy

print

?

#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

print

?

#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

?

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...