转自:https://blog.csdn.net/f110300641/article/details/83822290

在ANSI C中,这些宏的定义位于stdarg.h中:

typedef char *va_list;

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

#define va_start(list,param1)   ( list = (va_list)&param1+ sizeof(param1) )

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

#define va_arg(list,mode)   ( (mode *) ( list += sizeof(mode) ) )[-1]

va_end宏,清空va_list可变参数列表:

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

注:以上sizeof()只是为了说明工作原理,实际实现中,增加的字节数需保证为为int的整数倍

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

为了理解这些宏的作用,我们必须先搞清楚:C语言中函数参数的内存布局。首先,函数参数是存储在栈中的,函数参数从右往左依次入栈。

以下面函数为讨论对象:

void test(char *para1,char *param2,char *param3, char *param4) { va_list list; ...... return; }

在linux中,栈由高地址往低地址生长,调用test函数时,其参数入栈情况如下:

当调用va_start(list,param1) 时:list指针指向情况对应下图:

最复杂的宏是va_arg。

  1.  
    #include <stdio.h>
  2.  
    #include <stdarg.h>
  3.  
     
  4.  
    void var_test(char *format, ...)
  5.  
    {
  6.  
    va_list list;
  7.  
    va_start(list,format);
  8.  
     
  9.  
    char *ch;
  10.  
    while(1)
  11.  
    {
  12.  
    ch = va_arg(list, char *);
  13.  
     
  14.  
    if(strcmp(ch,"") == 0)
  15.  
    {
  16.  
    printf("\n");
  17.  
    break;
  18.  
    }
  19.  
    printf("%s ",ch);
  20.  
    }
  21.  
    va_end(list);
  22.  
    }
  23.  
     
  24.  
    int main()
  25.  
    {
  26.  
    var_test("test","this","is","a","test","");
  27.  
    return 0;
  28.  
    }

附:可变参数应用实例

1.printf实现

  1.  
    #include <stdarg.h>
  2.  
     
  3.  
    int printf(char *format, ...)
  4.  
    {
  5.  
    va_list ap;
  6.  
    int n;
  7.  
     
  8.  
    va_start(ap, format);
  9.  
    n = vprintf(format, ap);
  10.  
    va_end(ap);
  11.  
    return n;
  12.  
    }

2.定制错误打印函数error

  1.  
    #include <stdio.h>
  2.  
    #include <stdarg.h>
  3.  
     
  4.  
    void error(char *format, ...)
  5.  
    {
  6.  
    va_list ap;
  7.  
    va_start(ap, format);
  8.  
    fprintf(stderr, "Error: ");
  9.  
    vfprintf(stderr, format, ap);
  10.  
    va_end(ap);
  11.  
    fprintf(stderr, "\n");
  12.  
    return;
  13.  

va_list 、va_start、 va_arg、 va_end 使用说明【转】的更多相关文章

  1. va_list/va_start/va_arg/va_end深入分析【转】

    转自:http://www.cnblogs.com/justinzhang/archive/2011/09/29/2195969.html va_list/va_start/va_arg/va_end ...

  2. C++省略参数(va_list va_start va_arg va_end)的简单应用

    原文参考自:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html #include <iostream> #in ...

  3. va_list/va_start/va_arg/va_end深入分析

    http://www.cnblogs.com/justinzhang/archive/2011/09/29/2195969.html

  4. va_start,va_arg,va_end的使用

    一.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表. void fun(...); void fun(parm_list,...); #include <stdi ...

  5. va_list、va_start和va_end使用

    我们知道va_start,va_arg,va_end是在stdarg.h中被定义成宏的,由于1.硬件平台的不同 2.编译器的不同,所以定义的宏也有所不同. 在ANSI C中,这些宏的定义位于stdar ...

  6. va_start(),va_end()函数应用【转】

    转自:http://www.cnblogs.com/gogly/articles/2416833.html 原理解释: VA_LIST 是在C语言中解决变参问题的一组宏,在<stdarg.h&g ...

  7. va_start(),va_end()函数应用

    原理解释: VA_LIST 是在C语言中解决变参问题的一组宏,在<stdarg.h>头文件下. VA_LIST的用法:            (1)首先在函数里定义一具VA_LIST型的变 ...

  8. 深入C语言可变参数(va_arg,va_list,va_start,va_end,_INTSIZEOF)

    一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,…),int ...

  9. OC可变參数的函数实现va_start、va_end、va_list的使用

    一.简单介绍 我们常常在编程的时候看见类似这种代码,如图1.1 图1.1 或者是这种可变參数,如图1.2 图1.2 二.基本知识介绍 在学习怎样写这样的格式的函数前,先简介几个经常使用的宏: 下面摘自 ...

随机推荐

  1. bootstrap如何去除自带的样式----导航栏中的菜单实现平滑的过渡到对应的菜单区域-------动态跟换模态框中的内容

    问题1:如何去除bootstap中css中自带的overflow:hidden这个样式 今天遇见在bootstap中轮播图上的  附带图  片不能够显示出来,图片始终有一部分的高度  被隐藏了 后来通 ...

  2. luoguP4343自动刷题机(二分标准题)

    https://www.luogu.org/problem/P4343 参考博客:https://www.luogu.org/blog/ofnoname/solution-p4343 这真是一语点醒梦 ...

  3. 【转】HTTPS建立连接的过程

    原文链接:https://www.cnblogs.com/shiqi17/p/9756880.html https://www.jianshu.com/p/bd75ab32ae57 HTTP建立连接的 ...

  4. Ant风格路径表达式

    ANT通配符有三种: ? 匹配任何单字符 * 匹配0或者任意数量的字符 ** 匹配0或者更多的目录 举例: /project/*.a 匹配项目根路径下所有在project路径下的.a文件 /proje ...

  5. luoguP3975 [TJOI2015]弦论

    题意 第一问有一个经典做法:学习笔记 对于第二问,其实就是对于一个状态的所有串,第一问看成一个,第二问看成多个. code: #include<bits/stdc++.h> using n ...

  6. rss订阅

    其实,本质上和爬虫没区别,只不过这是人家主动给你数据,而且是编排好格式后的数据 按个人主页url更新内容 去重,按照redis去重的方式 按时间保存内容 mysql 保存为时间格式(可以根据时间比较大 ...

  7. 第02组 Beta冲刺(3/5)

    队名:無駄無駄 组长博客 作业博客 组员情况 张越洋 过去两天完成了哪些任务 数据库实践的报告 提交记录(全组共用) 接下来的计划 加快校园百科的进度 还剩下哪些任务 学习软工的理论课 学习代码评估. ...

  8. windows/tomcat 修改java虚拟机JVM以utf-8字符集加载class文件的两种方式

      1.情景展示 做了这么长时间的java开发,但是,你知道JVM是以怎样的编码加载.解析class文件的吗? 我们知道,通常情况下,我们会将java文件的字符集修改成utf-8,这样,理所当然地就认 ...

  9. python-3-条件判断练习题

    前言 我们在前面两章学习了基础数据类型与条件判断语句,今天我们来做下练习题.如果你有不一样的解题思路在评论区亮出你的宝剑!!! 一.习题如下: 1.使用 while 循环输出 1 2 3 4 5 6 ...

  10. paramiko 远程执行多个命令

    转发博客如下 https://blog.csdn.net/c_base_jin/article/details/86561445