printf,sprintf,vsprintf,vsnprintf的区别 您所在的位置:网站首页 sprintf不输出 printf,sprintf,vsprintf,vsnprintf的区别

printf,sprintf,vsprintf,vsnprintf的区别

2024-02-15 20:39| 来源: 网络整理| 查看: 265

最熟悉的不用说就是printf了,居然有了printf为什么还要有别的输出函数哪?当然是因为有不同的用途。

1.printf和sprintf的区别

先看看两个函数的原型

/* Write formatted output to stdout. */ extern int printf (const char *__restrict __format, ...); /* Write formatted output to S. */ extern int sprintf (char *__restrict __s, const char *__restrict __format, ...) __THROWNL;

sprintf比printf多了一个参数,也就是第一个参数char __restrict __s,其实就是个char类型的字符串。而且源码注释也解释的非常清楚——Write formatted output to S.也就是结果会保存到用户传入的第一个字符串参数里面。相对于是一个缓存。而printf源码注释也解释的非常清楚——Write formatted output to stdout.——是直接输出到stdout,也就是标准输出。

看下面的例子就能明白sprintf的用法:

int main(int argc, char *argv[]) { char buff[15]; int a=10; sprintf(buff,"sprintf %d\n",a); return 0; }

输出:

buff size 11

通过调用sprintf后,buff里面确实有值了,而且size是11。而且不会把buff的内容输出到屏幕(标准输出stdout)上。写到这sprintf的语法已经全部讲完了,sprintf唯一的作用就是向char *buff里面写内容。不输出我怎么知道里面有内容呢?你可以debug,也可以用printf输出,但是对于后者,可能是多此一举。看下面的例子

int main(int argc, char *argv[]) { char buff[15]; int a=10; sprintf(buff,"sprintf %d\n",a); printf("buff %s\n",buff); return 0; }

输出:

buff sprintf 10

为什么说是多此一举?因为sprintf就是不是用来打印输出到屏幕用的,他就是专门用来输出内容到char* buff里面的。printf才是专门用来输出到屏幕上的。我们可以看下printf的实现。

int __printf (const char *format, ...) { va_list arg; int done; va_start (arg, format); done = __vfprintf_internal (stdout, format, arg, 0);//输入了stdout va_end (arg); return done; }

在__vfprintf_internal这个函数调用的地方传入了stdout.也就是标准输出对象,所以printf默认就是用来向屏幕输出的。

小结:

printf是专门用来先屏幕输出的,也就是标准输出stdout。而sprintf就是专门用来输出内容到字符串的。

2.vsprintf和sprintf的区别

前面已经解释了sprintf和printf的区别,那么这个vsprintf又是做什么用的?先来看下两者的声明:

/* Write formatted output to S. */ extern int sprintf (char *__restrict __s, const char *__restrict __format, ...) __THROWNL; /* Write formatted output to S from argument list ARG. */ extern int vsprintf (char *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __THROWNL;

两者唯一的区别就是第三个参数,sprintf的第三个参数是可变列表,而vsprintf的第三个参数是__gnuc_va_list __arg,这是个什么东西?其实这也是可变列表,只是形式不一样而已。后者实际上是专门为C语言默认的可变列表做了封装,使之操作更灵活。相对于你可以给可变参数当成一个变量,这样就有更多的操作空间了。注释也就是的非常清楚——Write formatted output to S from argument list ARG.——格式化输出到字符串中,内容来源是参数列表,也就是__gnuc_va_list __arg。

要想再解释的更加清楚就不得不提stdarg.h这个头文件。这个头文件就是用来操作可变列表的。 在stdarg.h中__gnuc_va_list被typedef成va_list,比较原来的太长了不方便。

typedef __gnuc_va_list va_list;

到目前为止,我们只需要知道va_list约等于可变参数符号…(三个点)。来看下面的例子:

int main(void) { double s, t; s = sum(3, 1.1, 2.5, 13.3); t = sum(6, 1.1, 2.1, 13.1, 4.1, 5.1, 6.1); printf("return value for " "sum(3, 1.1, 2.5, 13.3): %g\n", s); printf("return value for " "sum(6, 1.1, 2.1, 13.1, 4.1, 5.1, 6.1): %g\n", t); return 0; } double sum(int lim, ...) { va_list ap; // 声明一个对象储存参数 double tot = 0; int i; //va_start(va_list ap, last_arg),last_arg表示参数列表前一个参数,这里是lim va_start(ap, lim); // 把ap初始化为参数列表 for (i = 0;i va_list ap; // 声明一个对象储存参数 double tot = 0; int i; va_start(ap, lim); // 把ap初始化为参数列表 char buff[30];//如果数组的值太小会报*** stack smashing detected ***: terminated vsprintf(buff,"result:------%g %g %g %g %g\n",ap); printf("buff %s\n",buff); va_end(ap); // 清理工作 return tot; }

注意里面的vsprintf函数,有5个%占位符,只有一个输出变量ap。 小结:

vsprintf就是为了更方便的将可变参数输出到字符串缓存。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有