stdarg详解

c中的stdarg

  • 一、简述
  • 二、接口定义
  • 三、原理
  • 四、例子

一、简述

stdarg的全称是standard arguments(标准参数),是基于函数参数压栈特性来实现的,主要目的就是为了让函数能够接收可变参数。

二、接口定义

stdarg接口是线程安全的。

/* 初始化句柄va_list, last是函数第一个参数,也是式化字符串format 例如:printf("hello %s", str)中的"hello %s"*/
void va_start(va_list ap, last); 

/* 基于句柄va_list,去遍历下一个type类型并返回 */
type va_arg(va_list ap, type);

/* 释放句柄va_list */
void va_end(va_list ap);

/* 深拷贝va_list */
void va_copy(va_list dest, va_list src);

三、原理

1.va_list句柄其实就是char *类型的栈指针。
2.acpi_native_int的作用是内存对齐。(64位机器上是8字节 32位机器上是4字节)
3.va_start:获取函数栈首地址赋值给ap并偏移ap
4.va_arg:获取参数偏移ap
5.va_end: 将ap赋值为NULL

#ifndef _VALIST
#define _VALIST
typedef char *va_list;
#endif				/* _VALIST */

/* Storage alignment properties */

#define  _AUPBND                (sizeof (acpi_native_int) - 1)
#define  _ADNBND                (sizeof (acpi_native_int) - 1)

/* Variable argument list macro definitions */

#define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap)              (ap = (va_list) NULL)
#define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))

四、例子

#include 
#include 

void
foo(char *fmt, ...)
{
    va_list ap;
    int d;
    char c, *s;

    va_start(ap, fmt);
    while (*fmt)
        switch (*fmt++) {
        case 's':              /* string */
            s = va_arg(ap, char *);
            printf("string %s\n", s);
            break;
        case 'd':              /* int */
            d = va_arg(ap, int);
            printf("int %d\n", d);
            break;
        case 'c':              /* char */
            /* need a cast here since va_arg only
               takes fully promoted types */
            c = (char) va_arg(ap, int);
            printf("char %c\n", c);
            break;
        }
    va_end(ap);
}

你可能感兴趣的:(linux)