欢迎使用CSDN-markdown编辑器

  1. printf 函数说明如下:
    函数原型:printf(const char *format,[argument]);
    第一个参数是一个格式化字符串,后面是与格式化字符串中的代码相对应的不同类型多个参数。

  2. * sprintf() 用于将输出存到字符缓冲中。*
    函数原型:sprintf(char *buffer, const char *format, [argument]);
    第一个参数是字符串缓冲区,后面是一个格式字串。sprintf不是将格式化结果标准输出,而是将其存入szBuffer。该函数返回该字符串的长度。
    在命令行程序中,
    printf (“The sum of %i and %i is %i”, 5, 3, 5+3) ;
    的功能相同于
    char szBuffer [100] ;
    sprintf (szBuffer, “The sum of %i and %i is %i”, 5, 3, 5+3) ;
    puts (szBuffer) ;
    在Windows中,使用MessageBox显示结果优于puts。
    几乎每个人都经历过,当格式化字符串与被格式化的变数不合时,可能使printf 执行错误并可能造成程序当掉。使用sprintf 时,您不但要担心这些,而且还有一个新的负担:您定义的字符串缓冲区必须足够大以存放结果。Microsoft 专用函数_snprintf 解决了这一问题,此函数引进了另一个参数,表示以字节计算的缓冲区大小。

  3. vsprintf 函数
    函数原型:int vsprintf(char *string, char *format, va_list param);
    既然sprintf() 与 vsprintf() 功能类似,为什么不统一下,而且 vsprintf() 用法如此麻烦呢?
    假设你想封装一个子函数 Myprintf() ,其功能是将格式化字符串输出两遍,若用 sprintf() 实现:

void Myprintf(const char* fmt,...)
{
  char s[10];
  sprintf(s,fmt);
  puts(s);
  puts(s);
}

当调用该函数时:

int a=1,b=2;
Myprintf("a=%d,b=%d",a,b);

输出:

a=?,b=?
a=?,b=?

我也不知道它会输出几,但一定不会是 a=1,b=2 。
这显然是错误的!
为什么呢?
当你这么调用 Myprintf() 时,其中的sprintf() 实际上是这样的:
sprintf(s,”a=%d,b=%d”)
而不是:
sprintf(s,”a=%d,b=%d”,a,b) !!
因为这么调用的话只能解析到第一个字符串而无法解析到后面的参数。
所以类似这种封装用 sprintf() 是无法实现的,使用 sprintf() 只能原始的为它输入所有的参数而不能以传参的方式给它。
若用 vsprintf()那么这个问题就可以迎刃而解。
函数如下:

void Myprintf(const char* fmt,...)
{
  char s[10];
  va_list ap;
  va_start(ap,fmt);
  vsprintf(s,fmt,ap);
  va_end(ap);
  puts(s);
  puts(s);
}

输出:

a=1,b=2
a=1,b=2

详细解释下:
vsprintf 是sprintf 的一个变形,它只有三个参数。vsprintf 用于执行有不定数量参数的函数,类似printf 格式。vsprintf的前两个参数与sprintf相同:一个用于保存结果的字符串缓冲区和一个格式化字符串。第三个参数是指向格式化参数队列的指针。实际上,该指针指向在堆栈中供函数调用的变量。va_list、va_start和va_end宏(在STDARG.H中定义)帮助我们处理堆栈指针。

首先你要知道函数执行时,函数的参数是倒序压入栈中的,vsprintf() 为了能够解析你传给它的多个参数,你必须告诉它参数从哪里开始。
vadefs.h 头文件中这么定义 :typedef char * va_list,于是我们定义了一个 va_list ap 来保存参数起始地址。
va_start(ap,fmt) 就找出这个函数在栈中排列的一堆参数的起始地址,然后直接浏览栈中参数,并用 vsprintf() 实现格式化字符串的读取,最后 vs_end(ap) 释放ap,就像释放指针一样。通俗地说就是因为 vsprintf() 比 sprintf() 更加接近底层(栈),因此能实现这个目的,也是因此能用 vsprintf() 来实现 sprintf()。


http://blog.csdn.net/raito__/article/details/48860119
http://blog.csdn.net/anye3000/article/details/6593551

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值