`
啸笑天
  • 浏览: 3445253 次
  • 性别: 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");
}
 

 

 

分享到:
评论

相关推荐

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

    1)首先在函数里定义一个va_list型的变量,这里是arg_ptr,这个变 量是指向参数的指针. 2)然后用va_start宏初始化变量arg_ptr,这个宏的第二个参数是第 一个可变参数的前一个参数,是一个固定的参数. 3)然后用va_arg返回...

    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-list原理解释

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

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

    可变参数的函数原理其实很简单,而va系列是以宏定义来定义的,实现跟堆栈相关.我们写一个可变函数的C函数时,有利也有弊,所以在不必要的场合,我们无需用到可变参数。如果在C++里,我们应该利用C++的多态性来实现可变参数...

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

    关于可变参数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_...

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

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

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

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

    printf函数实现详解

    这个示例中,我们可以看到 printf 函数使用 va_list 来存储参数,并使用 va_start 和 va_arg 宏来访问参数。 四、printf 函数的实现流程 printf 函数的实现流程可以分为以下几个步骤: 1. va_start(ap, format); ...

    C语言中的可变参数

    3. 必须在函数内部使用 `va_start` 和 `va_end`,并且每个 `va_start` 需对应一个 `va_end`。 4. 不能在可变参数列表中使用浮点数或结构体,因为它们的大小可能因编译器而异。通常,只能使用基本数据类型(如 int, ...

    《Head First C》P344-345

    `stdarg.h`库提供了`va_list`、`va_start`、`va_arg`和`va_end`等宏,它们是处理可变参数的核心工具。 首先,`va_list`是一个类型定义,用于声明一个变量来存储可变参数列表的指针。例如: ```c va_list args; ``` ...

    C语言可变参数的使用

    这个头文件包含了一些关键的函数和类型定义,如`va_list`、`va_start`、`va_arg`和`va_end`,它们是处理可变参数的关键。 1. `va_list`:这是一个类型定义,用于存储可变参数列表的指针。通常我们会声明一个`va_...

    水滴石穿C语言之可变参数问题.doc

    `printf` 的实现依赖于 `&lt;stdarg.h&gt;` 提供的工具,如 `va_list`,`va_start`,`va_arg` 和 `va_end`。 1. `va_list` 是一个类型别名,通常用于表示可变参数列表的迭代器。它是一个指针,用于遍历可变参数列表。 2. ...

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

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

    参数-VA-ARGS- 与...的用法与区别

    例如,C++中的`std::va_list`和`va_start`、`va_arg`、`va_end`等函数可以配合`...`使用来处理可变参数。一个简单的例子是: ```cpp void printArgs(int count, ...) { va_list args; va_start(args, count); ...

    c语言变参函数--转载[定义].pdf

    3. `va_end`: 当处理完所有可变参数后,使用`va_end`宏来清理`va_list`。它只有一个参数,即`va_list`变量。例如:`va_end(arg_ptr)`。 在提供的示例代码中,`simple_va_fun`函数展示了如何使用这些宏来处理可变...

Global site tag (gtag.js) - Google Analytics