printf函数族你了解吗
printf 函数族
絮絮叨叨
printf 应该是学习C语言的第一个函数,我们都知道它是用于字符串格式化输出的。但是它的用法你真正了解了吗?
printf 系列函数不仅仅可用用来打印字符串到控制台,还可以向其他标准IO或者数组中格式化输出。
01
printf 函数族简介
printf 函数是定义在 stdio.h 中的函数,属于C标准库。不同编译器实现过程不同,在这并不会详细描述它的底层实现原理。只针对printf函数族的使用。
printf 函数族共有8个函数:
其中8个函数可分为两大类,每一类中都有一个相互对应。例如:printf 和 vprintf 两个函数为一对。其功能完全一样,不同点在于参数格式。
printf函数参数使用不定参数(...)传递参数,vprintf 使用参数列表(va_list) 传递参数。
02
printf 函数族功能介绍
int printf (const char * _format, ...);
printf是我们使用最多的一个函数,其功能为把格式化之后的字符串输出到标准输出流中。
大多数时候标准输出是控制台的显示,不过在MCU中,我们经常会将标准输出重定向到串口,然后通过串口查看信息。
所有printf函数族的返回值是:写入字符串成功返回写入的字符总数,写入失败则返回一个负数。
int sprintf (char * _s, const char * _format, ...);
sprintf 功能与printf 类似,不过它是将字符串格式化输出到它的第一个参数所指定的字符数组中。
由于它是输出到字符数组,则存在数组大小不足或者传递参数非法,导致格式化后的字符溢出的情况,导致缓冲区后面的栈/堆数组被修改。
更推荐使用 snprintf 函数代替 sprintf 函数。
int fprintf (FILE* _s, const char * _format, ...);
fprintf 功能与printf 类似,但它的输出是流(FILE *) 中。这个流可以是标准输出(stdout)、标准错误(stderr)或者文件 (FILE *fd)。
也就是说 fprintf 可以直接向系统中文件格式化输出字符串。
int snprintf (FILE* _s,size_t size, const char * _format, ...);
snprintf 是 sprintf 的升级版,它解决了 sprintf 可能存在的缓冲区溢出问题。
它的第一个参数和 sprintf 一样,指定了一个字符数组存放格式化后的字符串,不过在它的第二个参数中指定了缓冲区数组的大小。
如果格式化字符串超过缓冲区数组大小,则进行截断,超出部分不进行输出。
03
printf 参数
接下来是本次的重点:格式化输出的参数。
printf 函数族的格式化参数属性相同,下面以 printf 为例讲解字符串格式属性。
printf 格式化控制属性格式如下:
%[flags][width][.prec][length]type
%[标志][最小宽度][.精度][类型长度]类型
1. type(类型)
type 是格式控制字符的类型,为必选项。在 printf 中会根据类型对应的格式去栈中读取对应大小的数据,务必保证参数类型和参数的数据类型保持一致。
type 支持的类型如下所示:
2. flags(标志)
flags 用于规定输出样式。例如我们有时需要对其打印多个数字,但是数组长度并不是固定的,此时可以使用flag参数进行设置。
例如:左对齐打印四个数字,1,12,123,1234。
flag 支持参数如下:
3. number(宽度)
字符宽度有固定和可变两种类型。固定宽度为在类型前面加一个数字表示宽度:
printf("num is %8d\n",1234);
可变宽度类型是指在格式化的宽度可由一个变量来指定,在程序中使用一个星号(*)进行占位,然后在参数中指定宽度。
printf("num is %*d\n",8,1234);
4. precision(精度)
精度的属性格式只有一个,对不同类型的效果不同。具体描述见下图:
精度的属性常用在格式化浮点数时使用:
printf("float : %2.3f\n",1.23);
输出结果为:float : 1.230
5. length(类型长度)
类型长度用于修饰type(类型)的长度。比如在打印一个 uint64_t 类型的无符号整形数字时,应该使用%llu来进行格式化输出。
其中ll为修饰类型的长度为long long 的整形。
04
结语
printf 函数族是标准输入输出库中的标准输出部分,其还有一个更加强大 scanf 函数族,这个就留给后面有时间在来写了~
吐槽一句,本来以为很简单的一个 printf 函数讲解,没想到写完这篇文章还是用了两个多小时。。。
永远不要低估一件事的难度!
THE
END
这里是非典型技术宅,点击上方蓝字关注
如果本文对你有帮助
那就来个点赞👍,收藏⭐,再看👀~
点击原文在CSDN查看我更多博客
微信号|非典型技术宅
往期推荐 ·
Cortex M33 内核初体验
单片机复位电路详解
C语言预处理指令之include
从编码到运行-程序编译过程详解