如何把va_list可变参数传送到下一级函数中(如传送到printf)
最近我在一个LCD上想实现打印格式化字符串的功能,实现这样的功能可有两种方式:
一 最直接的就是自己去解析类似于printf功能的一个函数;
二 比较简单的方法是使用已有的sprintf功能,把格式化字符串打印到一个字符缓冲区中,再将这个字符缓冲区打印到LCD上来。
这里选择了第二种方法!
我已经把这个嵌入式程序弄到pc机上来运行了,第一次编写的代码是这样子的:
#include <stdio.h>
#include <stdarg.h> void lcm_appendf(const char *fmt, ...)
{
char fm_buffer[];
int fm_len = ;
fm_len = snprintf(fm_buffer, , fmt); printf("fm_len = %d\r\n", fm_len);
printf("%s", fm_buffer);
} int main(int argc, char **args)
{
char c; // printf("Hello, this is Merlin Dec:%d, Hex:0x%x, Str:%s\r\n", 254, 0x32, "tfAna");
lcm_appendf("Hello, this is Merlin Dec:%d, Hex:%x, Str:%s\r\n", , 0x32, "tfAna");
scanf("%c", &c);
}
编译时提示错误:
$ gcc lcm_appendf.c
lcm_appendf.c: In function ‘lcm_appendf’:
lcm_appendf.c::: warning: format not a string literal and no format arguments [-Wformat-security]
lcm_appendf.c::: warning: format not a string literal and no format arguments [-Wformat-security]
表示没有格式参数!原来我忘记把格式(%d%x%s)对应的参数(254 0x32 "tfAna")写上去。所以先加上,这些可变参数,就是lcm_appendf的“第二个参数”...
直接写成snprintf(fm_buffer, , fmt, ...)显然是不行的!那么我怎么把lcm_appendf中的...转化为snprintf可以接受的参数呢?答案是使用va_list这个可变参数类型。
所以修改后的代码变成这样子:
#include <stdio.h>
#include <stdarg.h> void lcm_appendf(const char *fmt, ...)
{
char fm_buffer[];
int fm_len = ;
va_list ap; va_start(ap, fmt);
fm_len = snprintf(fm_buffer, , fmt, ap);
va_end(ap); printf("fm_len = %d\r\n", fm_len);
printf("%s", fm_buffer);
} int main(int argc, char **args)
{
char c; // printf("Hello, this is Merlin Dec:%d, Hex:0x%x, Str:%s\r\n", 254, 0x32, "tfAna");
lcm_appendf("Hello, this is Merlin Dec:%d, Hex:%x, Str:%s\r\n", , 0x32, "tfAna");
scanf("%c", &c);
}
这时再编译就不再有什么错误提示了,但运行之后的结果是这样子的:

乱码!
网上百度了一圈没有找到答案,然后google了一下国外网站,看到stackoverflow上有人也有同样的问题
http://stackoverflow.com/questions/5977326/call-printf-using-va-list
原来,得使用vprintf啊!对应于我这里就是使用vsnprintf了。(参考这个函数的用法http://en.cppreference.com/w/cpp/io/c/vfprintf)
再修改源码为:
#include <stdio.h>
#include <stdarg.h> void lcm_appendf(const char *fmt, ...)
{
char fm_buffer[];
int fm_len = ;
va_list ap; va_start(ap, fmt);
fm_len = vsnprintf(fm_buffer, , fmt, ap);
va_end(ap); printf("fm_len = %d\r\n", fm_len);
printf("%s", fm_buffer);
} int main(int argc, char **args)
{
char c; // printf("Hello, this is Merlin Dec:%d, Hex:0x%x, Str:%s\r\n", 254, 0x32, "tfAna");
lcm_appendf("Hello, this is Merlin Dec:%d, Hex:%x, Str:%s\r\n", , 0x32, "tfAna");
scanf("%c", &c);
}
结果就正确了:

如何把va_list可变参数传送到下一级函数中(如传送到printf)的更多相关文章
- 【转载】va_list 可变参数 简介 va_copy vprintf
[说明]本文转载自 smart 的文章 http://blog.sina.com.cn/s/blog_590be5290100qhxr.html 及百度百科 va_list是一个宏,由va_star ...
- va_list可变参数
可变参数函数实现 va_list,va_start,va_arg,va_end va可变参数意思,variable-argument. 1. 头文件及实现 linux中定义在gcc头文件中,stdar ...
- js求和运算在可变参数的情况下ES3、ES5和ES6的写法区别
//ES3.ES5的写法 function foo(){ var arr = Array.prototype.slice.call(arguments); var sum = 0; arr.forEa ...
- C++ 11可变参数接口设计在模板编程中应用的一点点总结
概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量 ...
- volatile,可变参数,memset,内联函数,宽字符窄字符,国际化,条件编译,预处理命令,define中##和#的区别,文件缓冲,位域
1.volatile: 要求参数修改每次都从内存中的读取.这种情况要比普通运行的变量需要的时间长. 当设置了成按照C99标准运行之后,使用volatile变量之后的程序运行的时间将比register的 ...
- String filePath = request.getSession().getServletContext().getRealPath("/");这句话返回的路径是什么,解释下getRealPath("/")函数中的"/"表示什么意思
request.getSession().getServletContext() 获取的是Servlet容器对象,相当于tomcat容器了.getRealPath("/") 获取实 ...
- MySQL下concat函数中null值问题
在mysql中,使用CONCAT(str1,str2,...)函数拼接字符串的过程中,如果你拼接的字段当中有值为null,那么拼接的结果就为null 注: select CONCAT(字段1,字段2) ...
- 深入C语言可变参数(va_arg,va_list,va_start,va_end,_INTSIZEOF)
一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,…),int ...
- C语言可变参数va_list
一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,-) int ...
随机推荐
- OpenGL路(四)自制的图形功能(立方体、汽缸、圆锥)
#include <gl/glut.h> #include <gl/GLU.h> #include <gl/GL.h> #pragma comment(lib, & ...
- 它们的定义TextView使之具有跑马灯的效果
一.引入问题 使用通用textview快乐效应,焦点事件不启动滚动,button目前的焦点事件,但丑,因此,需要定制TextView 天生焦点 个textview FocusedTextView.ja ...
- SQL Server 2008 R2 性能计数器详细列表(一)
原文:SQL Server 2008 R2 性能计数器详细列表(一) SQL Server Backup Device 计数器: 可监视用于备份和还原操作的 Microsoft SQL Server ...
- PC远程调试设备(转)
我们在移动端进行前端开发时,会遇到一个让人头痛但不得不面对的问题——调试. 在 PC 机器上,我们有功能强大的 Chrome DevTools.Firebug,即便是老版本的 IE ,我们也可以安装微 ...
- VB6基本数据库应用(五):数据的查找与筛选
同系列的第五篇,上一篇在:http://blog.csdn.net/jiluoxingren/article/details/9633139 数据的查找与筛选 第4篇发布到现在已经过了4天,很抱歉,学 ...
- c++读取文本文件
#include<iostream> #include<fstream> using namespace std; int main() { int a,b=-100000,c ...
- iOS 生成随机颜色(UIColor)
#import <UIKit/UIKit.h> @interface UIColor (RandomColor) +(UIColor *) randomColor; @end #impor ...
- Javascipt数组去重的几种方式
方法一 function unique(arr) { var retArr = []; for (var i = 0; i < arr.length; i++) { (retArr.indexO ...
- ORA-12638: 无法检索身份证明 解决的方法
the NTS option makes the Oracle client attempt to use your current Windows domain credentials to aut ...
- 比float更好的页面布局inline-block
一:页面布局的发展过程 桌格设计 表格+css div+css的浮动布局 div+css的内联块布局 二:流行多年的浮动布局的优劣 优势: div+css浮动布局的优势,主要是相对于table布局来说 ...