對va_list; va_start ; va_end ;vsprintf理解(轉)


 以下為轉載內容:

 1 int printf(const char* fmt, ...)  2 {  3  va_list args;  4     int i;  5     //1.將變參轉化為字符串
 6  va_start(args,fmt);  7     vsprintf((char *)outbuf, fmt, args);  8  va_end();  9     //2. 打印字符串到串口
10     for(i=0;i< strlen((char *)outbuf); i++) 11  { 12  putc(outbuf[i]); 13  } 14     return i; 15 }

其中va_list( VA_LIST 是在C語言中解決變參問題的一組宏):va_list表示可變參數列表類型,實際上就是一個char指針fmt

然后是va_start:va_start用於獲取函數參數列表中可變參數的首指針(獲取函數可變參數列表) 

         1、輸出參數args(類型為va_list): 用於保存函數參數列表中可變參數的首指針(即,可變參數列表)

         2、輸入參數fmt: args指向fmt后面的參數,為第一個參數的前一個參數,是一個固定參數

vsprintf((char *)outbuf, fmt, args):送格式化輸出到串中 ,函數說明:vsprintf()會根據參數fmt 字符串來轉換並格式化數據, 然后將結果復制到參數char(*)outbuf 的字符串數組, 直到出現字符串結束('\0')為止.

va_end():va_end用於結束對可變參數的處理。

對於這段代碼的理解:
 printf函數首先定義了一個char指針fmt,然后后面緊跟的是printf的變參,那么變參轉換就開始了,下一個函數va_start定義了一個指向變參的首指針args,緊接着利用vsprintf函數,按照fmt格式以及通過args指針,將變參一個個按照規定好的格式轉換數據,結果復制到char(*)outbuf這個數組中,最后結束可變參數處理。

這里我對於fmt這個指針的理解是,定義了一個指針類型,轉換結果就是按照這個指針的類型轉換的,這里轉換的結果就是將變參轉換成char字符型

 

以上為轉載內容


C可變參數

  希望函數帶有可變數量的參數,而不是預定義數量的參數。C 語言為這種情況提供了一個解決方案,它允許定義一個函數,能根據具體的需求接受可變數量的參數。下面的實例演示了這種函數的定義。

 1 int func(int, ... ) 
 2 {
 3    .
 4    .
 5    .
 6 }
 7 
 8 int main()
 9 {
10    func(2, 2, 3);
11    func(3, 2, 3, 4);
12 }

 

函數 func() 最后一個參數寫成省略號,即三個點號(...),省略號之前的那個參數是 int,代表了要傳遞的可變參數的總數。為了使用這個功能,您需要使用 stdarg.h 頭文件,該文件提供了實現可變參數功能的函數和宏。具體步驟如下:

  • 定義一個函數,最后一個參數為省略號,省略號前面可以設置自定義參數。
  • 在函數定義中創建一個 va_list 類型變量,該類型是在 stdarg.h 頭文件中定義的。
  • 使用 int 參數和 va_start 宏來初始化 va_list 變量為一個參數列表。宏 va_start 是在 stdarg.h 頭文件中定義的。
  • 使用 va_arg 宏和 va_list 變量來訪問參數列表中的每個項。
  • 使用宏 va_end 來清理賦予 va_list 變量的內存。

【例程】

 1 void b_print(const char *fmt, ...)  2 {  3   uint8_t r_index = 0,i;  4   char str[256];  5   static uint8_t skip_flag = 0x00;  6   char *pdata;  7   memset(str,0,256);  8  va_list args; //定義一個va_list類型的變量args  9  va_start(args, fmt);//獲取函數參數列表中可變參數的首指針,即緊跟fmt后面的參數,故args用來保存函數參數列表中可變參數的首指針 10  vsprintf(str,fmt,args); 11  va_end(args); 12   /* JSON 剔除格式化輸出字符 */
13   pdata = str; 14 }

關於vsprintf(str,fmt,args); //使用參數列表發送格式化輸出到字符串

[fmt]:這是字符串,包含了要被寫入到字符串 str 的文本。它可以包含嵌入的 fmt 標簽,fmt 標簽可被隨后的附加參數中指定的值替換,並按需求進行格式化。fmt 標簽屬性是 %[flags][width][.precision][length]specifier,具體講解如下:

specifier(說明符) 輸出
c 字符
d 或 i 有符號十進制整數
e 使用 e 字符的科學科學記數法(尾數和指數)
E 使用 E 字符的科學科學記數法(尾數和指數)
f 十進制浮點數
g 自動選擇 %e 或 %f 中合適的表示法
G 自動選擇 %E 或 %f 中合適的表示法
o 有符號八進制
s 字符的字符串
u 無符號十進制整數
x 無符號十六進制整數
X 無符號十六進制整數(大寫字母)
p 指針地址
n 無輸出
% 字符

 

flags(標識) 描述
- 在給定的字段寬度內左對齊,默認是右對齊(參見 width 子說明符)。
+ 強制在結果之前顯示加號或減號(+ 或 -),即正數前面會顯示 + 號。默認情況下,只有負數前面會顯示一個 - 號。
(space) 如果沒有寫入任何符號,則在該值前面插入一個空格。
# 與 o、x 或 X 說明符一起使用時,非零值前面會分別顯示 0、0x 或 0X。
與 e、E 和 f 一起使用時,會強制輸出包含一個小數點,即使后邊沒有數字時也會顯示小數點。默認情況下,如果后邊沒有數字時候,不會顯示顯示小數點。
與 g 或 G 一起使用時,結果與使用 e 或 E 時相同,但是尾部的零不會被移除。
0 在指定填充 padding 的數字左邊放置零(0),而不是空格(參見 width 子說明符)。


width(寬度) 描述
(number) 要輸出的字符的最小數目。如果輸出的值短於該數,結果會用空格填充。如果輸出的值長於該數,結果不會被截斷。
* 寬度在 format 字符串中未指定,但是會作為附加整數值參數放置於要被格式化的參數之前。


.precision(精度) 描述
.number 對於整數說明符(d、i、o、u、x、X):precision 指定了要寫入的數字的最小位數。如果寫入的值短於該數,結果會用前導零來填充。如果寫入的值長於該數,結果不會被截斷。精度為 0 意味着不寫入任何字符。
對於 e、E 和 f 說明符:要在小數點后輸出的小數位數。
對於 g 和 G 說明符:要輸出的最大有效位數。
對於 s: 要輸出的最大字符數。默認情況下,所有字符都會被輸出,直到遇到末尾的空字符。
對於 c 類型:沒有任何影響。
當未指定任何精度時,默認為 1。如果指定時不帶有一個顯式值,則假定為 0。
.* 精度在 format 字符串中未指定,但是會作為附加整數值參數放置於要被格式化的參數之前。


length(長度) 描述
h 參數被解釋為短整型或無符號短整型(僅適用於整數說明符:i、d、o、u、x 和 X)。
l 參數被解釋為長整型或無符號長整型,適用於整數說明符(i、d、o、u、x 和 X)及說明符 c(表示一個寬字符)和 s(表示寬字符字符串)。
L 參數被解釋為長雙精度型(僅適用於浮點數說明符:e、E、f、g 和 G)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM