1. 程式人生 > >va_start、va_end、va_list的使用

va_start、va_end、va_list的使用

1:當無法列出傳遞函式的所有實參的型別和數目時,可用省略號指定引數表
void foo(...);

void foo(parm_list,...);

2:函式引數的傳遞原理

函式引數是以資料結構:棧的形式存取,從右至左入棧.eg:

#include <iostream>

void fun(int a, ...)

{

int *temp = &a;  temp++;

for (int i = 0; i < a; ++i)

{

cout << *temp << endl;

temp++;

}

int main()

{

int a = 1;

int b = 2;

int c = 3;

int d = 4;

fun(4, a, b, c, d);

system("pause");

return 0;

}
Output::

1

2

3

4

3:獲取省略號指定的引數
在函式體中宣告一個va_list,然後用va_start函式來獲取引數列表中的引數,使用完畢後呼叫va_end()結束。像這段程式碼:

void TestFun(char* pszDest, int DestLen, const char* pszFormat, ...)

{

va_list args;

va_start(args, pszFormat);

_vsnprintf(pszDest, DestLen, pszFormat, args);

va_end(args);

}

4.va_start使argp指向第一個可選引數。va_arg返回引數列表中的當前引數並使argp指向引數列表中的下一個引數。va_end把argp指標清為NULL。函式體內可以多次遍歷這些引數,但是都必須以va_start開始,並以va_end結尾。

1).演示如何使用引數個數可變的函式,採用ANSI標準形式

  #include 〈stdio.h〉

  #include 〈string.h〉

  #include 〈stdarg.h〉

  int demo( char*, ... );

  void main( void )

  {

     demo("DEMO", "This", "is", "a", "demo!", "");

  }

  int demo( char* msg, ...)

  {      

     va_list argp;

     int argno = 0;

     char* para; 

        va_start( argp, msg);

       while (1)      

{

        para = va_arg( argp, char*);

         if ( strcmp( para, "") == 0 )

          break;

         printf("Parameter #%d is: %s\n", argno, para);

         argno++;  

}

   va_end( argp );  

   return 0;

  }

2)//示例程式碼1:可變引數函式的使用
#include "stdio.h"

#include "stdarg.h"

void simple_va_fun(int start, ...)

{

va_list arg_ptr;

int nArgValue =start;

   int nArgCout=0;     //可變引數的數目

va_start(arg_ptr,start);

//以固定引數的地址為起點確定變參的記憶體起始地址。

    do

    {

       ++nArgCout;

        printf("the %d th arg: %d\n",nArgCout,nArgValue);    

//輸出各引數的值

        nArgValue = va_arg(arg_ptr,int);                     

//得到下一個可變引數的值

    } while(nArgValue != -1);           

   return;

}

int main(int argc, char* argv[])
{

simple_va_fun(100,-1);

simple_va_fun(100,200,-1);

    return 0;

}

3)//示例程式碼2:擴充套件——自己實現簡單的可變引數的函式。
下面是一個簡單的printf函式的實現,參考了<The C Programming Language>中的例子

#include "stdio.h"

#include "stdlib.h"

void myprintf(char* fmt, ...)       

//一個簡單的類似於printf的實現,//引數必須都是int 型別

{

char* pArg=NULL;              

//等價於原來的va_list

    Char c;   

    pArg = (char*) &fmt;     

     //注意不要寫成p = fmt

!!因為這裡要對//引數取址,而不是取值
    pArg +=sizeof(fmt);        

 //等價於原來的va_start       
   
do
    {
        c
=*fmt;
        if (c !=
'%')
       
{
           
putchar(c);           
//照原樣輸出字元
       
}
       
else
       
{
          
//按格式字元輸出資料
          
switch(*++fmt)
          
{
           
case'd':
               
printf("%d",*((int*)pArg));          
               
break;
           
case'x':
               
printf("%#x",*((int*)pArg));
               
break;
           
default:
               
break;
           
}
            pArg +=
sizeof(int);              
//等價於原來的va_arg
       
}
        ++fmt;
   
}while (*fmt != '\0');
    pArg =
NULL;                              
//等價於va_end
    return;
}
int main(int argc, char*
argv[])
{
    int i = 1234;
    int j =
5678;
   
    myprintf("the first
test:i=%d\n",i,j);
    myprintf("the secend test:i=%d;
%x;j=%d;\n",i,0xabcd,j);
   
system("pause");
    return 0;
}

相關推薦

va_startva_endva_argva_listfprintf vfprintf用法解釋

今天有個需求寫檔案,所有研究了一下標題的函式: 首先要使用va_start等這些方法需要包含標頭檔案: #include<stdarg.h> 直接上程式碼說明: int MyWriteFile(char *format, ...) { va_list paramL

va_startva_endva_list的使用

1:當無法列出傳遞函式的所有實參的型別和數目時,可用省略號指定引數表 void foo(...); void foo(parm_list,...); 2:函式引數的傳遞原理 函式引數是以資料結構:棧的形式存取,從右至左入棧.eg: #include <iostre

va_startva_endva_arg 實現可變長引數

/*******************************///va_start、va_end、va_arg 實現可變長引數/*******************************/ #include <stdarg.h>#include <stdio.h> #def

linux核心細節-va_argva_endva_startprintf

#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd))) #define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T,

【轉】C++可變參數列表處理宏va_listva_startva_end的使用

sin 不同 struct rto snprintf 指定 cnblogs 最小 多個 VA_LIST是在C語言中解決變參問題的一組宏他有這麽幾個成員: 1)va_list型變量: #ifdef _M_ALPHA typedef struct{ char*  

va_list va_start va_arg va_end 使用說明

在ANSI C中,這些巨集的定義位於stdarg.h中: typedef char *va_list; va_start巨集,獲取可變引數列表的第一個引數的地址(list是型別為va_list的指標,param1是可變引數最左邊的引數): #define va_start(list,pa

va_listva_startva_end使用

我們知道va_start,va_arg,va_end是在stdarg.h中被定義成巨集的,由於1、硬體平臺的不同 2、編譯器的不同,所以定義的巨集也有所不同。 在ANSI C中,這些巨集的定義位於stdarg.h中,典型的實現如下: typedef char *va_list; va_start巨集,獲

va_listva_startva_argva_end巨集的使用(轉)

當你的函式的引數個數不確定時,就可以使用上述巨集進行動態處理,這無疑為你的程式增加了靈活性。 Example: CString AppendString(CString str1,...)//一個連線字串的函式,引數個數可以動態變化{      LPCTSTR str=str

iOS開發可變引數va_listva_startva_end

iOS 可變引數(va_list,va_start,va_end) 例如:UIAlertView的init方法中的otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION

理解va_listva_startva_argva_end原理及使用方法

在程式設計中應該注意的問題和解決辦法雖然可以通過在堆疊中遍歷引數列表來讀出所有的可變引數,但是由於不知道可變引數有多少個,什麼時候應該結束遍歷,如果在堆疊中遍歷太多,那麼很可能讀取一些無效的資料.解決辦法:a.可以在第一個起始引數中指定引數個數,那麼就可以在迴圈還中讀取所有的可變引數;b.定義一個結束標記,在

va_listva_startva_end 巨集用法小結

直奔主題,在VS幫助文件中va_list、va_start、va_end的說明是: type va_arg(    va_list arg_ptr,    type ); void va_end(    va_list arg_ptr );

va_listva_startva_argva_end的原理與使用 (轉)

概述由於在C語言中沒有函式過載,解決不定數目函式引數問題變得比較麻煩;即使採用C++,如果引數個數不能確定,也很難採用函式過載.對這種情況,有些人採用指標引數來解決問題.下面就c語言中處理不定引數數目的問題進行討論. 定義大家先看幾巨集.在VC++6.0的include有

深度探索va_startva_argva_end

 採用C語言程式設計的時候,函式中形式引數的數目通常是確定的,在呼叫時要依次給出與形式引數對應的所有實際引數。但在某些情況下希望函式的引數個數可以根據需要確定。典型的例子有大家熟悉的函式printf()、scanf()和系統呼叫execl()等。那麼它們是怎樣實現的呢?  

對巨集定義:_INTSIZEOF(n)va_start(ap,v)va_arg(ap,t)va_end(ap)的理解

程式碼:typedef char * va_list; #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) #define va_start(ap,v) (

【轉】C/C++中可變引數的詳細介紹(va_list,va_start,va_arg,va_end)

  可變引數的函式原理其實很簡單,而va系列是以巨集定義來定義的,實現跟堆疊相關.我們寫一個可變函式的C函式時,有利也有弊,所以在不必要的場合,我們無需用到可變引數。如果在C++裡,我們應該利用C++的多型性來實現可變引數的功能,儘量避免用C語言的方式來實現。   由於在C語言中沒有函式過載,解決不定數目函

(最短路徑算法整理)dijkstrafloydbellman-fordspfa算法模板的整理與介紹

void empty borde fast 默認 grand else 理解 scan 這一篇博客以一些OJ上的題目為載體。整理一下最短路徑算法。會陸續的更新。。。 一、多源最短路算法——floyd算法 floyd算法主要用於求隨意兩點間的最短路徑。也成

sql 實現用戶名郵箱手機號登錄

append nes class select logs lec email mobile () StringBuilder strSql = new StringBuilder(); strSql.Append("se

8.1 加減日

加減 val nth ear edate tno minus date bsp select hiredate - interval 5 day as hd_minus_5D, hiredate + interval 5 day as hd_

[HTML]表單控件iframedatailsmetertimefieldsetmark

單選 spa 多行 普通 -html tag sel legend doctype 一、表單元素 1.input:空標記 屬性: type:文本框、密碼框、單選按鈕、復選框 value:當前表單元素的值,可以是提交給服務器的值,也可以是默認顯示的初始值 name:名稱,要提

malloccallocrealloc和alloca各種的區別

calloc 一次 單元 不支持 new span 初始化 har 堆棧 需要先包含頭文件 #include"malloc.h" malloc是標準的在堆中開辟新的空間 比如 char *pt=(char *)malloc(10*sizeof(char)); 需要free(