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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353022.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 根据时间范围自动算间隔_Java根据开始时间结束时间计算时间间隔 x年x月x日...

最近项目中有这样的需求&#xff1a;根据租赁开始时间租赁结束时间计算租期x年x月x日&#xff0c;相同的需求还有根据出生日期计算年龄等等......例如&#xff1a;开始日期 2020年7月24日 结束日期 2021年9月3日 租期 1年1月11日&#xff1b;开始日期 2020年7月24日 结束日期…

会java的鸭子_鸭子在Java中打字? 好吧,不完全是

会java的鸭子根据维基百科&#xff0c;鸭子的打字是&#xff1a; 动态类型的类型&#xff0c;其中对象的方法和属性确定有效的语义&#xff0c;而不是其从特定类或特定接口的实现继承 用简单的话 当我看到一只鸟走路像鸭子&#xff0c;游泳像鸭子&#xff0c;嘎嘎像鸭子一样时…

数据结构(六)查找---多路查找树(2-3-4树)

一&#xff1a;2-3-4树 具体操作同2-3树 2-3-4树是2-3树的扩展&#xff0c;包括了4节点的使用&#xff0c;一个4节点包含小中大三个元素和四个孩子&#xff08;或没有孩子&#xff09;。 &#xff08;一&#xff09;插入实现 构建一个数组为{7,1,2,5,6,9,8,4,3}的2-3-4树的过程…

java web 静态_「Java Web」主页静态化的实现

一个站点的主页一般不会频繁变动&#xff0c;而大多数用户在訪问站点时不过浏览一下主页(未登陆)。然后就离开了。对于这类訪问请求。假设每次都要通过查询数据库来显示主页的话&#xff0c;显然会给server带来多余的压力。这时候我们能够将主页静态化。在减轻数据库server压力…

实现Java监视的12个步骤程序存在缺陷

Java监视的当前状态最大的问题是什么&#xff1f; 生产中的错误很像喝醉的短信。 您只有在事情已经发生之后才意识到出了点问题。 发短信日志通常比应用程序错误日志更有趣&#xff0c;但是……两者都同样难以修复。 在本文中&#xff0c;我们将执行一个12步的监视漏洞修复程…

创建django项目

1.新建django项目 打开命令行&#xff0c;进入想要安置项目的目录&#xff0c;命令行输入&#xff1a;django-admin startproject my_web 用Pycharm打开 2.开启服务器 命令行进入my_web目录。输入&#xff1a;python manage.py runserve开启服务器&#xff0c; 将服务器的地址复…

有关fwrite语句的用法

一&#xff1a;函数名: fwrite 功 能: 写内容到流中 用 法:fwrite(buffer,size,count,fp); &#xff08;1&#xff09;buffer&#xff1a;是一个指针&#xff0c;对fwrite来说&#xff0c;是要输出数据的地址。 &#xff08;2&#xff09;size&#xff1a;要写入的字节数&#…

json 全文索引 mysql_MySQL全文索引、联合索引、like查询、json查询速度大比拼

查询背景有一个表tmp_test_course大概有10万条记录&#xff0c;然后有个json字段叫outline&#xff0c;存了一对多关系(保存了多个编码&#xff0c;例如jy1577683381775)我们需要在这10万条数据中检索特定类型的数据&#xff0c;目标总数据量&#xff1a;条2931SELECT COUNT(*)…

java从端口获取数据库_Java之通过接口获取数据并用JDBC存储到数据库中

最近做数据同步功能&#xff0c;从接口获取数据然后存到数据库中以便后续对数据进行相关操作&#xff0c;下面就贴一下相关代码。1 import com.alibaba.fastjson.JSON;2 import com.alibaba.fastjson.JSONObject;34 public class Digests {5 private static final String APPKE…

支付宝H5 与网页端支付开发

在日常生活中&#xff0c;我们基本上都是进行微信与支付宝的支付方式尽心支付&#xff0c;这种方式确实大大便利了我们的生活&#xff0c;那么如何在我们的产品中进行微信与支付宝支付的植入开发呢&#xff1f; 我们先进行支付宝的H5与网页端支付开发&#xff0c;这里只进行支付…

C/C++中extern关键字详解

1 基本解释&#xff1a;extern可以置于变量或者函数前&#xff0c;以标示变量或者函数的定义在别的文件中&#xff0c;提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。 也就是说extern有两个作用&#xff0c;第一个,当它与"C"…

javaone_JavaOne 2012:NetBeans.Next –未来路线图

javaone我从Continental Ballroom 4和一个NetBeans主题&#xff08; Easel项目 &#xff09;到Continental Ballroom 5&#xff0c;走了必要的几个步骤&#xff0c;以查看另一个面向NetBeans的演示文稿&#xff1a;“ NetBeans.Next –未来路线图”。 Ashwin Rao着手介绍羽毛之…

java简单编译器源代码_25行代码实现一个简单的编译器

起因《25行JavaScript语句实现一个简单的编译器》实现的是一个简单到不能再简单的玩具的玩具&#xff0c;他的魔法是函数式编程简化了js代码。java 8提供了函数式编程的支持&#xff0c;昨晚脑子抽风突然兴趣java也可以实现一个如此简单的编译器&#xff01;java和js语言差异ja…

《python网络数据采集》读后感 第六章:读取文档

1.文档编码&#xff1a; 文档编码是一种告诉程序——无论是计算机的操作系统还是 Python 代码——读取文档的规 则。文档编码的方式通常可以根据文件的扩展名进行判断&#xff0c;虽然文件扩展名并不是由编码 确定的&#xff0c;而是由开发者确定的。例如&#xff0c;如果我把 …

如何在Gradle多项目构建中管理依赖项

从很早以前我就一直喜欢Gradle构建工具。 它的潜力甚至在1.0版本之前就已经很明显了&#xff0c;那时变化经常被打破。 如今&#xff0c;升级很少会引起意外。 该工具已经成熟并且运行良好。 Gradle包括一个功能强大的依赖项管理系统&#xff0c;该系统可以与Maven和Ivy存储库…

Linux下nm和ldd 命令

1. Linux nm 命令 nm [‘-a’|‘--debug-syms’] [‘-g’|‘--extern-only’] [‘-B’] [‘-C’|‘--demangle’[style]] [‘-D’|‘--dynamic’] [‘-S’|‘--print-size’] [‘-s’|‘--print-armap’] [‘-A’|‘-o’|‘--print-file-name’][‘--special-syms’] [‘-n’|‘…

mysql alter table_mysql ALTER TABLE 的用法

在表格被建立在资料库中后&#xff0c;我们常常会发现&#xff0c;这个表格的结构需要有所改变。常见的改变如下&#xff1a;加一个栏位删去一个栏位改变栏位名称改变栏位的资料种类以上列出的改变并不是所有可能的改变。ALTER TABLE 也可以被用来作其他的改变&#xff0c;例如…

WEB开发技术点

做为一个WEb类MIS的开发者&#xff0c;涉及的知识点很多&#xff0c;总结成图&#xff0c;方便自已学习 转载于:https://www.cnblogs.com/ezezwyj/p/9515859.html

mysql8中怎么增删一列_MYSQL 第八课 数据的增删改

#DML语言/*数据操作语言&#xff1a;插入&#xff1a;insert修改&#xff1a;update删除&#xff1a;delete*/#一、插入语句#方式一&#xff1a;经典的插入/*语法&#xff1a;insert into 表名(列名,...) values(值1,...);*/SELECT * FROM beauty;#1.插入的值的类型要与列的类型…

c++中new和delete的使用方法

new和delete运算符用于动态分配和撤销内存的运算符 new用法: 1. 开辟单变量地址空间 1)new int; //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a new int 即为将一个int类型的地址赋值给整型指针a. 2)int *a new int(5) 作用同上,但是同时将整数赋…