vsnprintf va_list va_start va_end

1、函数原型:

int vsnprintf(char *str, size_t size, const char *format, va_list ap);

某度百科:

_vsnprintf是C语言库函数之一,属于可变参数。用于向字符串中打印数据、数据格式用户自定义。

头文件是#include <stdarg.h>。

函数功能:将可变参数格式化输出到一个字符数组。

2、参数说明

  1. char *str [out],把生成的格式化的字符串存放在这里.指向存储结果C字符串的缓冲区的指针。
    缓冲区应至少有n个字符的大小。

  2. size_t size [in], str可接受的最大字符数 (非字节数,UNICODE一个字符两个字节),防止产生数组越界.生成的字符串的长度至多为n-1,为额外的终止空字符留下空间。size_t是一个无符号整数类型。

  3. const char *format [in], 指定输出格式的字符串,它决定了你需要提供的可变参数的类型、个数和顺序。包含格式字符串的C字符串,其格式字符串与printf中的格式相同

  4. va_list ap [in], va_list变量. va:variable-argument:可变参数,标识使用va_start初始化的变量参数列表的值。
    va_list是在<cstdarg>中定义的特殊类型。

  5. 返回值:

    如果n足够大,则会写入的字符数,不包括终止空字符。
    如果发生编码错误,则返回负数。
    注意,只有当这个返回值是非负值且小于n时,字符串才被完全写入。

3、vsnprintf和_vsnprintf(一个多了横杠)一样吗

vsnprintf和_vsnprintf用法应该差不多,是不是一样的,我也还没有结论,

但某度百科,有备注:

linux环境下是:vsnprintf

VC6环境下是:_vsnprintf

是不是一样这里我也不给出结论,下面只讲linux下的vsnprintf

4、查看资料

在linux下可以自己使用命令行查看使用方法

在linux下使用man vsnprintf回车可以看到右上角有个PRINTF(3),3可以知道这是个库函数(不是系统调用或者其他的,详细见附文,man的参数说明),并且可以知道vsnprintf的使用方法,摘抄如下:

SYNOPSIS
       #include <stdio.h>

       int printf(const char *format, ...);
       int fprintf(FILE *stream, const char *format, ...);
       int sprintf(char *str, const char *format, ...);
       int snprintf(char *str, size_t size, const char *format, ...);

       #include <stdarg.h>
       int vprintf(const char *format, va_list ap);
       int vfprintf(FILE *stream, const char *format, va_list ap);
       int vsprintf(char *str, const char *format, va_list ap);
       int vsnprintf(char *str, size_t size, const char *format, va_list ap);

//翻到最底下还有例程
       #include <stdio.h>
       #include <stdlib.h>
       #include <stdarg.h>

       char * make_message(const char *fmt, ...)
       {
           int n;
           int size = 100;     /* Guess we need no more than 100 bytes */
           char *p, *np;
           va_list ap;

           if ((p = malloc(size)) == NULL)
               return NULL;

           while (1) {

               /* Try to print in the allocated space */

               va_start(ap, fmt);
               n = vsnprintf(p, size, fmt, ap);
               va_end(ap);

               /* Check error code */

               if (n < 0)
                   return NULL;

               /* If that worked, return the string */
                if (n < size)
                   return p;

               /* Else try again with more space */

               size = n + 1;       /* Precisely what is needed */

               if ((np = realloc (p, size)) == NULL) {
                   free(p);
                   return NULL;
               } else {
                   p = np;
               }
           }
       }

4、网上查看其他资料

到网上其他博客查资料,可以知道vsnprintf一般用于可变参数的解析中,将可变参数格式化输出到一个字符数组。

通常和va_list 、va_start 、va_end 这几个联合使用。

man  va_start可查到

       #include <stdarg.h>

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

 

va_list是一个宏,由va_start和va_end界定。

    typedef char* va_list;
  void va_start ( va_list ap, prev_param );
  type va_arg ( va_list ap, type );
  void va_end ( va_list ap );
    其中,va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。

<Step 1> 在调用参数表之前,应该定义一个 va_list 类型的变量,以供后用(假设这个 va_list 类型变量被定义为ap);
 <Step 2> 然后对 ap 进行初始化,让它指向可变参数表里面的第一个参数。这是通过 va_start 来实现的,其第一个参数是 ap 本身,第二个参数last是变量前面最后一个参数的名称参数列表,即调用函数已知其类型的最后一个参数。因为此参数的地址可能会在va_start()中使用宏,则不应将其声明为寄存器变量或函数操作或数组类型。va_start()宏将初始化ap以供va_arg()和va_end()后续使用,并且必须首先调用。

   <Step 3> 然后是获取参数,调用 va_arg。调用va_arg的例子见下面它的第一个参数是 ap,第二个参数是要获取的参数的指定类型,并返回这个指定类型的值,同时把 ap 的位置指向变参表的下一个变量位置;或者调用vsnprintf见上面。
   <Step 4> 获取所有的参数之后,我们有必要将这个 ap 指针关掉,以免发生危险,方法是调用 va_end。它是将输入的参数 ap 置为 NULL,应该养成获取完参数表之后关闭指针的习惯。

int max(int n, ...)  // 定参 n 表示后面变参数量,定界用,输入时切勿搞错
{                  
 va_list ap;       // 定义一个 va_list 指针来访问参数表
 va_start(ap, n);     // 初始化 ap,让它指向第一个变参
 int maximum = -0x7FFFFFFF;   // 这是一个最小的整数
 int temp;
 for(int i = 0; i < n; i++)
 {
  temp = va_arg(ap, int);   // 获取一个 int 型参数,并且 ap 指向下一个参数
  if (maximum < temp)
   maximum = temp;
 }
 va_end(ap);       // 善后工作,关闭 ap
 return maximum;
}

// 在主函数中测试 max 函数的行为(C++ 格式,vc6.0)
int main()
{
 cout << max(3, 10, 20, 30) << endl;
 cout << max(6, 20, 40, 10, 50, 30, 40) << endl;
}

 

 

 

 

附:

linux可以通过man来查询一些函数的使用方法(巧记:小学老师教学生遇到问题找警察,linux下遇到问题还是需要找男人(man),哈哈哈)

man查看对应的一些数字代表的意义。

1、Standard commands (标准命令)

2、System calls (系统调用)

3、Library functions (库函数)

4、Special devices (设备说明)

5、File formats (文件格式)

6、Games and toys (游戏和娱乐)

7、Miscellaneous (杂项)

8、Administrative Commands (管理员命令)

9 其他(Linux特定的), 用来存放内核例行程序的文档

 

 

本文参考自以下互联网文章,如果有侵权请及时联系删除。

https://blog.csdn.net/swif_N_F/article/details/78712315

https://baike.baidu.com/item/_vsnprintf/5395011?fr=aladdin

https://blog.csdn.net/taotaost/article/details/52894192

http://blog.sina.com.cn/s/blog_590be5290100qhxr.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值