`
啸笑天
  • 浏览: 3472268 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

va_start、va_arg、va_end、va_list的使用

 
阅读更多

VA_LIST 是在C语言中解决变参问题的一组宏

他有这么几个成员:

1) va_list型变量:

#ifdef  _M_ALPHA
typedef struct {
        char *a0;       /* pointer to first homed integer argument */
        int offset;     /* byte offset of next parameter */
} va_list;
#else
typedef char *  va_list;
#endif

2)_INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍:

#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

3)VA_START宏,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数):

#define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )

4)VA_ARG宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型):

#define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

5)VA_END宏,清空va_list可变参数列表:

#define va_end(ap)      ( ap = (va_list)0 )

VA_LIST的用法:      
       (1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针;
       (2)然后用VA_START宏初始化变量刚定义的VA_LIST变量;
       (3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数);
       (4)最后用VA_END宏结束可变参数的获取。
使用VA_LIST应该注意的问题:
   (1)可变参数的类型和个数完全由程序代码控制,它并不能智能地识别不同参数的个数和类型;
   (2)如果我们不需要一一详解每个参数,只需要将可变列表拷贝至某个缓冲,可用vsprintf函数;
   (3)因为编译器对可变参数的函数的原型检查不够严格,对编程查错不利.不利于我们写出高质量的代码;

小结:可变参数的函数原理其实很简单,而VA系列是以宏定义来定义的,实现跟堆栈相关。我们写一个可变参数的C函数时,有利也有弊,所 以在不必要的场合,我们无需用到可变参数,如果在C++里,我们应该利用C++多态性来实现可变参数的功能,尽量避免用C语言的方式来实现。

 示例代码:
#include<stdio.h>
#include<stdarg.h>
void simple_va_fun(int start,...)
{
     va_list arg_ptr;
     int nArgValue = start;
     int nArgCount = 0;
     va_start(arg_ptr,start);
     do
     {
     ++nArgCount;
      printf("the %d the arg:%d\n",nArgCount,nArgValue);
       nArgValue=va_arg(arg_ptr,int);
    }while(nArgValue != -1);
    return; 
     }
main()
{
simple_va_fun(100,-1);
simple_va_fun(100,200,-1);
getchar();
      }
///////////////////
int writeMultiString(void *c, ...)
{
    va_list ap;
    const char *str;

    va_start(ap, c);
    str = va_arg(ap, const char *);

    while (str != NULL)
    {
        fputs(str, (FILE *)c);
        str = va_arg(ap, const char *);
    }

    va_end(ap);
    return 0;
}
 

 

// Quick Information Display
void show(id formatstring,...)
{
	va_list arglist;
	if (!formatstring) return;
	va_start(arglist, formatstring);
	id outstring = [[[NSString alloc] initWithFormat:formatstring arguments:arglist] autorelease];
	va_end(arglist);
	
	UIAlertView *av = [[[UIAlertView alloc] initWithTitle:@"LEAK DEMO" message:outstring delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
	[av show];
}

- (void) intro
{
	show(@"Run with Instruments using Leaks. Click a button to leak memory.%@\n",@"zyjzyj");
}
 

#define showAlert(format, ...) myShowAlert(__LINE__, (char *)__FUNCTION__, format, ##__VA_ARGS__)

// Simple Alert Utility
void myShowAlert(int line, char *functname, id formatstring,...)
{
    
	va_list arglist;
	if (!formatstring) return;
	va_start(arglist, formatstring);
	id outstring = [[[NSString alloc] initWithFormat:formatstring arguments:arglist] autorelease];
	va_end(arglist);
	
	NSString *filename = [[NSString stringWithCString:__FILE__ encoding:NSUTF8StringEncoding] lastPathComponent];
	NSString *debugInfo = [NSString stringWithFormat:@"%@:%d\n%s", filename, line, functname];
    
    UIAlertView *av = [[[UIAlertView alloc] initWithTitle:outstring message:debugInfo delegate:nil cancelButtonTitle:@"OK"otherButtonTitles:nil] autorelease];
	[av show];
}

- (void) rightAction: (id) sender
{
	showAlert(@"You pressed the right button");
}
 

 

 

分享到:
评论

相关推荐

    va_start、va_end、va_list的详细使用方法

    ### va_start、va_end、va_list的详细使用方法 #### 概述 在C语言中,函数参数的数量通常是固定的。然而,在某些情况下,我们可能希望一个函数能够接收可变数量的参数。例如,`printf`函数就是一个很好的例子,它...

    stdarg.h中三个宏va_start ,va_arg和va_end的应用

    ### stdarg.h中三个宏va_start,va_arg和va_end的应用详解 在C语言中,经常需要编写能够接受可变数量参数的函数。一个典型的例子就是`printf`函数,它可以接受任意数量和类型的参数。为了支持这种功能,C语言提供了...

    va_list(),va_start(),va_arg(),va_end() 详细解析

    写可变参数的C函数要在程序中用到以下这些宏: 代码如下:void va_start( va_list arg_ptr, prev_param );type va_arg( va_list arg_ptr, type );void va_end( va_list arg_ptr );va在这里是variable-argument(可变...

    va_arg_c_

    3. 一旦所有参数都被处理,记得使用`va_end`宏来清理`va_list`,这标志着可变参数列表的结束。 ```c va_end(args); ``` 4. 使用`va_arg`需要注意的是,必须按照参数实际传递的顺序和类型来使用。如果参数类型不...

    关于C/C++中可变参数的详细介绍(va_list,va_start,va_arg,va_end)

    这主要通过一组预定义的宏来实现,包括`va_list`、`va_start`、`va_arg`和`va_end`,这些宏定义在`stdarg.h`头文件中。下面我们将详细探讨这些宏的用途和工作原理。 1. `va_list`: `va_list`是一个类型定义,它...

    详解_C语言可变参数_va_list和_vsnprintf及printf实现

    这种灵活性主要由两个关键组件实现:`va_list`类型和宏`va_start`, `va_arg`和`va_end`。下面我们将逐一解析这些概念。 **`va_list`** `va_list`是一个特殊类型,用于存储可变参数列表的状态。当函数被调用时,`va...

    va-list原理解释

    1. 因为va_start, va_arg, va_end等定义成宏,所以它显得很愚蠢, 可变参数的类型和个数完全在该函数中由程序代码控制,它并不能智能地识别不同参数的个数和类型。 2. 另外还有一个问题,因为编译器对可变参数的函数...

    C语言中一些可变参数的用法

    本文讨论了C语言中可变参数的用法,包括如何写一个简单的可变参数的C函数,如何使用可变参数宏va_start、va_arg和va_end,以及可变参数在编译器中的处理。 一、写一个简单的可变参数的C函数 在C语言中,某些函数...

    C语言可变参数_va_list和_vsnprintf及printf实现.

    要使用`_va_list`,你需要包含`&lt;stdarg.h&gt;`头文件,然后利用`va_start`, `va_arg`和`va_end`宏来初始化和操作`_va_list`变量。 - `va_start`: 初始化`_va_list`变量,使其指向可变参数列表的第一个参数。 - `va_arg...

    test_va_args

    2. 使用`stdarg.h`库(C)或`&lt;cstdarg&gt;`库(C++)处理可变参数的三个关键宏:`va_start`、`va_arg`和`va_end`。 3. 如何在函数中定义和使用`va_list`,以及如何正确处理参数类型。 4. 通过实例展示了如何创建一个...

    # ##和 VA ARGS

    在这个例子中,`__VA_ARGS__` 捕获了`printf`格式化字符串后的所有参数,并在`vprintf`函数中使用`va_list`和`va_start`、`va_end`进行处理。 ### 可变参数函数 可变参数函数允许函数接受不同数量的参数。在C语言...

    C51可变参数讲解.pdf

    可变参数函数的实现主要包括几个宏:va_list, va_start, va_arg, va_end。下面将详细讲解这些宏以及它们的用法: 1. va_list: 这个类型用于声明一个变量,该变量会被用来遍历参数列表。在stdarg.h中,va_list被定义...

    c语言实现的一个简单的日志函数

    这个头文件中定义了`va_list`、`va_start`、`va_arg`和`va_end`宏,它们是处理可变参数列表的关键。下面逐一解释这些宏的作用: 1. `va_list`: 这是一个类型定义,用来声明一个可变参数列表的变量。例如:`va_list ...

    关于可变参数va系列函数用法的几个例子

    这种机制是通过一组特殊的宏实现的,包括`va_start`、`va_arg`、`va_end`和`va_copy`。本文将详细探讨这些宏的用法,并通过几个实际例子来阐述其工作原理。 ### 一、`va_start`宏 `va_start`是用于初始化可变参数...

    stdarg的用法(可变参数的用法)

    这个头文件声明的一个va_list的类型,和三个宏va_start,va_arg,va_end。我们可以生明一个va_list类型的变量,配合三个宏使用。 va_start(arg, last have name arg); 初始化之后,arg将指向第一个无名参数。 va_...

    有关va-list问题

    本文将深入探讨如何使用`va_list`、`va_start`、`va_arg`和`va_end`这四个宏来处理这种特殊的参数传递。 `va_list`是一个类型定义,它定义了一个可以存储变长参数列表中下一个参数地址的类型。在函数中,我们需要...

    C语言可变参数技术内幕.pdf

    va_start宏用于初始化可变参数表,va_arg宏用于取得当前的可变参数,va_end宏用于结束可变参数的使用。 va_start宏的原型为:void va_start(va_list ap, prev_param),其中ap是指向可变参数表的指针,prev_param是前...

    C语言变参函数设计

    - **内存管理**: 避免对`va_list`指针进行不当操作,确保在使用完毕后调用`va_end`。 #### 结论 C语言的变参函数设计提供了一种灵活的方式来处理参数数量不确定的情况,尤其是在需要处理多个类型和数量不定的参数...

Global site tag (gtag.js) - Google Analytics