Linux 下 va_start、va_end 学习及使用

news/2024/12/22 9:51:56/

本文主要介绍可变参数 函数的实现方法。

头文件:#include <stdarg.h>

一、函数系列介绍
1、va_start函数
原型:void va_start(va_list ap, last);
ap:va_list 类型的变量,指向参数的指针
last:最后一个显式声明的参数,以用来获取第一个变长参数的位置
2、va_arg函数
原型:type va_arg(va_list ap, type);
ap:va_list 类型的变量,指向参数的指针
type:指要获取的参数的类型
3、va_end函数
原型:void va_end(va_list ap);
ap:va_list 类型的变量,指向参数的指针
4、va_copy函数
原型:void va_copy(va_list dest, va_list src);

二、函数详细介绍

typedef char *  va_list;
#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) )#define va_start _crt_va_start
#define va_arg _crt_va_arg
#define va_end _crt_va_end#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap)      ( ap = (va_list)0 )

三、使用步骤介绍
1)定义一个va_list类型的变量,变量是指向参数的指针;
2)va_start初始化刚定义的变量,第二个参数是最后一个显式声明的参数;
3)va_arg返回变长参数的值,第二个参数是该变长参数的类型;
4)va_end将a)定义的变量重置为NULL。

四、示例
示例1:

void test_printf2(int num,...)
{va_list args;int i = 0;va_start(args,num);for(i; i < num; i++)printf("%d\n", va_arg(args, int));va_end(args);
}
test_printf2(3,1,2,3);

示例2:

void test_printf6(char *headData, char *format,...)
{char buff[4096];va_list args;memcpy(buff, headData, strlen(headData));va_start(args, format);vsnprintf(buff+strlen(headData), 1024, format, args);va_end(args);printf("%s\n", buff);
}test_printf6("requestData", "len is %d, data is %s", 10, "helloworld");

示例3:

void test_printf7(char *format,...)
{int tmpLen; char *buff, *buf, *ptr;va_list args;buff = (char *) malloc(sizeof(char)*1024);buf = buff; va_start(args, format);for (ptr = format; *ptr; ptr++) {if(*ptr == '%') {switch (*(++ptr)) {case 'd': *buff++ = va_arg(args, int) + 0x30;break;case 's':tmpLen = va_arg(args, int); memcpy(buff, va_arg(args, char *), tmpLen);buff += tmpLen;break;case 'c': *buff++ = va_arg(args, int);break;}} else{printf("%c\n", *ptr);}}   *buff = '\0';printf("%s\n", buf);//此处需注意打印要从头指针开始va_end(args);free(buf);//此处需注意释放的是头指针,否则会出现下面的错误buf = NULL;
}test_printf7("%d%d%s%c", 1,2,4,"helloWorld", 'E');

*** Error in `./a.out’: munmap_chunk(): invalid pointer: 0x0000000000e00047 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x77725)[0x7f982c4fa725]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x1a8)[0x7f982c506c18]
./a.out[0x401575]
./a.out[0x4015c8]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f982c4a3830]
./a.out[0x4006d9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:01 919832 /home/zx/test/a.out
00601000-00602000 r–p 00001000 08:01 919832 /home/zx/test/a.out
00602000-00603000 rw-p 00002000 08:01 919832 /home/zx/test/a.out
00e00000-00e21000 rw-p 00000000 00:00 0 [heap]
7f982c26d000-7f982c283000 r-xp 00000000 08:01 792176 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f982c283000-7f982c482000 —p 00016000 08:01 792176 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f982c482000-7f982c483000 rw-p 00015000 08:01 792176 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f982c483000-7f982c643000 r-xp 00000000 08:01 792138 /lib/x86_64-linux-gnu/libc-2.23.so
7f982c643000-7f982c842000 —p 001c0000 08:01 792138 /lib/x86_64-linux-gnu/libc-2.23.so
7f982c842000-7f982c846000 r–p 001bf000 08:01 792138 /lib/x86_64-linux-gnu/libc-2.23.so
7f982c846000-7f982c848000 rw-p 001c3000 08:01 792138 /lib/x86_64-linux-gnu/libc-2.23.so
7f982c848000-7f982c84c000 rw-p 00000000 00:00 0
7f982c84c000-7f982c872000 r-xp 00000000 08:01 792110 /lib/x86_64-linux-gnu/ld-2.23.so
7f982ca56000-7f982ca59000 rw-p 00000000 00:00 0
7f982ca6e000-7f982ca71000 rw-p 00000000 00:00 0
7f982ca71000-7f982ca72000 r–p 00025000 08:01 792110 /lib/x86_64-linux-gnu/ld-2.23.so
7f982ca72000-7f982ca73000 rw-p 00026000 08:01 792110 /lib/x86_64-linux-gnu/ld-2.23.so
7f982ca73000-7f982ca74000 rw-p 00000000 00:00 0
7ffe93f65000-7ffe93f86000 rw-p 00000000 00:00 0 [stack]
7ffe93ff0000-7ffe93ff2000 r–p 00000000 00:00 0 [vvar]
7ffe93ff2000-7ffe93ff4000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)

示例4:

void test_printf5(char *data, char *format,...)
{char buff[1024];char *tmpBuff, *ptr;va_list args;int tmpLen = 0;tmpBuff = buff; memset(tmpBuff, 0x00, sizeof(buff));memcpy(tmpBuff, data, strlen(data));tmpBuff += strlen(data);va_start(args, format); for(ptr = format; *ptr; ptr++) {switch (*ptr) {case 'd':*tmpBuff++ = va_arg(args, int) + 0x30;break;   case 's':    tmpLen = va_arg(args, int);*tmpBuff++ = tmpLen + 0x30;memcpy(tmpBuff, va_arg(args, char *), tmpLen);tmpBuff += tmpLen;break;case 'c':*tmpBuff++ = va_arg(args, int);break;}} va_end(args);*tmpBuff = '\0';    printf("%s\n", buff);return ;
}test_printf5("reqeustData", "dcdsdsc",2,'A',3,4,"buffer",5,3,"heloo",'C');

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

相关文章

va_list(可变参数函数的使用)

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

va_list函数

va_list是用来处理可变参数的&#xff0c;下面看一个示例。 #include "stdarg.h" #include <stdio.h>int test(char* msg, ...);int main() {test("hello", "wolrd",1);return 0; }int test(char* msg, ...) {va_list vaList; //定义一个…

va_start 用法

可以参考&#xff1a;C 标准库 - <stdarg.h> 1. 在C中&#xff0c;当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表 void foo(...); void foo(parm_list,...);这种方式和我们以前认识的不大一样&#xff0c;但我们要记住这是C中一种传参的形式…

检测到“_CRT_STDIO_ISO_WIDE_SPECIFIERS”的不匹配项

libboost_thread-vc142-mt-x64-1_82.lib(thread.obj) : error LNK2038: 检测到“_CRT_STDIO_ISO_WIDE_SPECIFIERS”的不匹配项: 值“0”不匹配值“1”(AcadStr.obj 中) 1> 正在创建库 x64\Release\ArxDbg.lib 和对象 x64\Release\ArxDbg.exp : fatal error LNK1319: 检测到 …

va_list分析

typedef char* va_list INTSIZEOF 宏,获取类型占用的空间长度&#xff0c;最小占用长度为int的整数倍&#xff1a; #define _INTSIZEOF(n) ( (sizeof(n) sizeof(int) - 1) & ~(sizeof(int) - 1) ) VA_START宏&#xff0c;获取可变参数列表的第一个参数的地址&#xff08…

va_start和va_end使用详解

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

va_list介绍

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

使用VA助手如何快速添加注释(按doxygen注释规范)

原文首发于微信公众号「3D视觉工坊」&#xff1a;使用VA助手如何快速添加注释(按doxygen注释规范) 首先&#xff0c;关于VA助手的破解安装教程&#xff0c;请参考&#xff1a;VS2015 Visual Assist X 破解版安装教程 此处分享一下我在工程中使用VA助手进行快速注释的小技巧&am…