va_list使用方法

news/2024/12/22 20:27:00/

转载自:http://blog.csdn.net/ID314846818/article/details/51074283

VA_LIST 是在C语言中解决变参问题的一组宏,变参问题是指参数的个数不定,可以是传入一个参数也可以是多个;可变参数中的每个参数的类型可以不同,也可以相同;可变参数的每个参数并没有实际的名称与之相对应,用起来是很灵活。

va_list 用法示例

#include <stdarg.h> int AveInt(int,...);void main()
{printf("%d/t",AveInt(2,2,3));printf("%d/t",AveInt(4,2,4,6,8));return;
}int AveInt(int v,...)
{int ReturnValue=0;int i=v;va_list ap ;va_start(ap,v);while(i>0){ReturnValue+=va_arg(ap,int) ;i--;}va_end(ap); return ReturnValue/=v;
}

VA_LIST的用法: 
(1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针; 
(2)然后用VA_START宏初始化变量刚定义的VA_LIST变量; 
(3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数); 
(4)最后用VA_END宏结束可变参数的获取。

上面是va_list的具体用法,下面讲解一下va_list各个语句含义(如上示例黑体部分)和va_list的实现。

     可变参数是由宏实现的,但是由于硬件平台的不同,编译器的不同,宏的定义也不相同,下面是VC6.0中x86平台的定义 :typedef char * va_list;     // TC中定义为void*#define _INTSIZEOF(n)    ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) //为了满足需要内存对齐的系统#define va_start(ap,v)    ( ap = (va_list)&v + _INTSIZEOF(v) )     //ap指向第一个变参的位置,即将第一个变参的地址赋予ap#define va_arg(ap,t)       ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )   /*获取变参的具体内容,t为变参的类型,如有多个参数,则通过移动ap的指针来获得变参的地址,从而获得内容*/#define va_end(ap) ( ap = (va_list)0 )   //清空va_list,即结束变参的获取

va_list ap ; 定义一个va_list变量ap 
va_start(ap,v) ;执行ap = (va_list)&v + _INTSIZEOF(v),ap指向参数v之后的那个参数的地址,即 ap指向第一个可变参数在堆栈的地址。 
va_arg(ap,t) , ( (t )((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )取出当前ap指针所指的值,并使ap指向下一个参数。 ap+= sizeof(t类型),让ap指向下一个参数的地址。然后返回ap-sizeof(t类型)的t类型指针,这正是第一个可变参数在堆栈里的地址。然后 用取得这个地址的内容。 
va_end(ap) ; 清空va_list ap。

使用VA_LIST应该注意的问题: 
(1)因为va_start, va_arg, va_end等定义成宏,所以它显得很愚蠢,可变参数的类型和个数完全在该函数中由程序代码控制,它并不能智能地识别不同参数的个数和类型. 也就是说,你想实现智能识别可变参数的话是要通过在自己的程序里作判断来实现的. 
(2)另外有一个问题,因为编译器对可变参数的函数的原型检查不够严格,对编程查错不利.不利于我们写出高质量的代码。 
(3)由于参数的地址用于VA_START宏,所以参数不能声明为寄存器变量,或作为函数或数组类型


http://www.ppmy.cn/news/222253.html

相关文章

2021-CISCN-fianl-ezj4va

2021-CISCN-fianl-ezj4va 前言 去年国赛决赛的0解Java&#xff0c;后来出现在了DASCTF八月挑战赛&#xff0c;当时不太会Java所以没有看&#xff0c;今天找个时间复现了一下。写的比较简单&#xff0c;具体可以看参考链接中的文章。 代码审计 访问/robots.txt得到文件名可以…

va_list深究

2011-04-21 21:06:11| 分类&#xff1a; C/C|字号 订阅 VA函数&#xff08;variable argument function&#xff09;&#xff0c;参数个数可变函数&#xff0c;又称可变参数函数。C/C编程中&#xff0c;系统提供给编程人员的va函数很少。*printf()/*scanf()系列函数&#xff0…

c语言va_start函数,va_start和va_end,以及c语言中的可变参数原理

FROM&#xff1a;http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html 本文主要介绍va_start和va_end的使用及原理。 在以前的一篇帖子Format MessageBox详解中曾使用到va_start和va_end这两个宏&#xff0c;但对它们也只是泛泛的了解。 介绍这两个宏之前先看一…

va start linux头文件,va_start/va_end函数-linux

#include void va_start(va_list ap, last); type va_arg(va_list ap, type); void va_end(va_list ap); void va_copy(va_list dest, va_list src); 1:当无法列出传递函数的所有实参的类型和数目时,可用省略号指定参数表 void foo(...); void foo(parm_list,...); 2:函数参数…

va_list语法

va_list &#xff08;1&#xff09;va_list类型&#xff0c;定义该类型变量来指向可变参数的地址。它的定义为&#xff1a; typedef char * va_list;&#xff08;2&#xff09;va_start(va_list, arg)&#xff0c;va_start初始化va_list变量&#xff0c;使得va_list变量指向…

MySQL 两个备机同时挂掉故障分析

来源&#xff1a; 接报线上出现两个5.7.38的备库同时crash&#xff0c;crash堆栈相同&#xff0c;内容如下&#xff1a; stack_bottom 7fd7700b0d30 thread_stack 0x40000 /home/service/app/mysql33066/bin/mysqld(my_print_stacktrace0x2c)[0xf1062c] /home/service/app/m…

Misumi米思米数据线驱动无法安装

Misumi米思米数据线驱动无法安装 • Win10 系统无法安装。 • 驱动只能在 XP 或 Win7 使用 • KCA-M538F-000 • M538F USB High Speed Serial Converter

Python 经纬度转化为米

import math from math import cosdef position_turn(Latitude,Longitude):参考地址&#xff1a;https://blog.csdn.net/Dust_Evc/article/details/102847870?utm_mediumdistribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-7.control&…