1.printf函数概述
在C语言中,printf函数作为标准库<stdio.h>的核心输出工具,通过灵活的格式化字符串机制,实现了对多种数据类型的高精度、可定制化输出。其基本语法为int printf(const char format, ...),其中format字符串包含普通文本与格式说明符,后续可变参数列表提供待输出的变量值。格式说明符以%开头,后接类型标识符(如d、f、c等),并可通过修饰符调整输出样式,这种设计使得开发者能够精确控制数据的显示格式,满足从简单调试到复杂报表生成的多样化需求。
格式说明符的类型标识符决定了数据的解析方式:%d用于输出有符号十进制整数,支持int、short等类型;%u对应无符号整数;%f默认输出6位小数的浮点数,而%e和%g则分别以科学计数法或自动选择%f/%e的紧凑形式呈现浮点数;字符与字符串通过%c和%s输出,其中字符串会自动追加空字符终止符;指针地址则通过%p以十六进制形式显示,通常配合void 类型使用。此外,%x和%X分别输出小写和大写的十六进制整数,%o用于八进制表示,这些进制转换功能在底层编程和位操作中尤为实用。
格式修饰符进一步扩展了输出控制能力。宽度修饰符通过%[数字]指定最小输出宽度,若实际数据长度不足,默认右对齐并用空格填充,例如printf("%5d", 42)输出" 42";结合-标志可改为左对齐(如printf("%-5d", 42)输出"42 ")。精度修饰符.[数字]对浮点数控制小数位数(如%.2f输出两位小数),对字符串则限制最大输出字符数(如printf("%.3s", "hello")输出"hel")。数字类型还可通过0标志用零填充(如printf("%05d", 42)输出"00042"),而+标志强制显示正负号(如printf("%+d", -5)输出"-5"),空格标志则对正数保留前导空格(如printf("% d", 5)输出" 5"),这些修饰符的组合使用(如printf("%+010.3f", 12.345))可生成高度规范化的数值输出。
特殊类型处理方面,printf通过%n将已输出字符数写入指定整型变量,这一特性在动态格式化中偶有应用,但需谨慎使用以避免安全风险。转义字符如\n(换行)、\t(制表符)、\(反斜杠)等可嵌入格式字符串,实现文本排版控制。对于非ASCII字符集(如中文),需确保源文件编码与终端编码一致,否则可能输出乱码;宽字符版本wprintf则专为Unicode设计,需配合<wchar.h>使用。
性能与安全性方面,printf因解析格式字符串的动态特性,相比直接输出函数(如puts)存在轻微性能开销,但在现代硬件上通常可忽略。其安全性风险主要源于格式字符串漏洞------若格式字符串来自用户输入且未经验证,恶意输入可能导致程序崩溃或信息泄露(如printf(user_input)可能引发任意内存读取)。因此,安全编码规范要求格式字符串必须为常量或严格验证的变量,或使用更安全的替代函数(如snprintf限制输出长度)。
综上,printf凭借其丰富的格式化能力,成为C语言输出操作的核心工具,广泛应用于调试日志、数据展示、交互界面等场景。开发者通过熟练掌握类型标识符、修饰符及标志的组合使用,能够高效实现从简单数值输出到复杂报表生成的多样化需求,同时需注意编码规范与安全实践以规避潜在风险。
2.函数原型
printf是C语言的标准输出函数,一般用于向标准输出设备按规定格式输出信息。函数原型如下:
c
#include <stdio.h>
int printf(const char *format, ...);
printf函数使用格式为:printf("<格式化字符串>",参量表);
printf()是C语言标准库函数,在stdio.h中定义。输出的字符串除了可以使用字母、数字、空格和一些数字符号以外,还可以使用一些转义字符表示特殊的含义。
字符串常量原样输出,在显示中起提示作用。输出表列中给出了各个输出项,要求格式控制字符串和各输出项在数量和类型上应该一一对应。其中格式控制字符串是以%开头的字符串,在%后面跟有各种格式控制符,以说明输出数据的类型、宽度、精度等。

3.printf输出字体颜色
在有些时候我们希望通过printf输出的内容以不同的颜色在终端展示,这样在调试过程看起来更加直观。
printf输出颜色时的控制命令:/033[A1;A2;A3m
-
/033[为固定开头;
-
m为固定结尾;
-
A1表示属性;
-
A2表示字体颜色;
-
A3表示背景颜色;
-
A1参数

-
A2参数

-
A3参数

-
示例
c
#include <stdio.h>
int main()
{
printf("\033[1;;41m%s\033[0m\n", "Hello World!");//字体加粗,背景为红色
//加下划线,字体颜色为黑色,背景为白色
printf("\033[4;30;47m%s\033[0m\n", "Hello World!");
printf("\033[5m%s\033[0m\n", "Hello World!");//字体闪烁
printf("\033[;34m%s\033[0m\n", "Hello World!");//设置字体为绿色
printf("\033[;;42m%s\033[0m\n", "Hello World!");//设置设置背景为绿色
}

- 其它属性信息
- \033[nA 光标上移n行
- \03[nB 光标下移n行
- \033[nC 光标右移n行
- \033[nD 光标左移n行
- \033[y;xH设置光标位置
- \033[2J 清屏
- \033[K 清除从光标到行尾的内容
- \033[s 保存光标位置
- \033[u 恢复光标位置
- \033[?25l 隐藏光标
- 0\33[?25h 显示光标
4.printf输出顺序
printf函数特性
- 特性1:从后往前计算
- 特性2:++/-- 在后面,表示真结束;
- ++/--在前面,则表示假结束,需要将最后的结果输出
- 特性3:输出的表达式若为赋值操作,则为假结束
示例1:
c
#include <stdio.h>
int main(void)
{
int z=4;
printf("%d,%d,%d,%d,%d,%d,%d\n",--z,z--,z++,z=100,z++,++z,--z);
//99 101 100 99 4 99 99
/*
printf函数特性
1.先从右往左匹配,计算结束为假结束,但自增/自减在后面的表达式为真结束。
2.再从左往右将值带入到所有假结束的表达式中,但不会对变量值做任何改变
上述打印可看做:printf("%d,%d,%d,%d,%d,%d,%d\n",A,B,C,D,E,F,G);
首先从右往左计算:
G=4-1=3 Z=3
F=3+1=4 Z=4
E=4 Z=Z+1=5 --真结束
D=100 Z=100
C=100 Z=Z+1=101 --真结束
B=101 Z=Z-1=100 --真结束
A=99 Z=Z-1=99
因此,Z最终的结果为99
再将Z的最终值,从左往右带入假表达式
A=99
B=101
C=100
D=Z=99
E=4
F=Z=99
G=Z=99
*/
示例2:
c
int x=10,y=20;
printf("x++ + +=%d,x++= %d,++y=%d\n",x++ + ++y,x++,++y);
//33 10 22
/*
上述打印可看做: printf("x++ + +=%d,x++= %d,++y=%d\n",A + B,C,D);
从右往左带入:
D=21 y=20+1=21
C=10 x=10+1=11 -->真结束
B=22 y=21+1=22
A=11 x=11+1=12 -->真结束
因此:x=12 y=22
再将x、y的最终值,从左往右带入假表达式
A+B=11+22=33
C=10
D=22
*/
}
示例3:
c
#include <stdio.h>
int main()
{
int arr[]={12,34,65,76,88,99};
int *p=arr;
//printf("%d %d %d\n",*p++,++*p,*p++);
//35 35 12
printf("p=%p\n",p);
//printf("%p %p %p %p\n",p++,++p,p+1,p++);
/*
printf("%p %p %p %p\n",p++,++p,p+1,p++);看做
printf("%p %p %p %p\n",A,B,C,D);
第一步:从后往前计算,根据++/--特性判断真假结束:
D=arr --> p=arr+1 -->真结束
C=arr+2 -->p=arr+1 -->真
B=arr+2 -->p=arr+2 -->假 --最后结果:arr+3
A=arr+2 -->p=arr+3 -->真
*/
printf("%p %p %p\n",p++,p=&arr[4],p++);
/* A B C
C=arr p=arr+1 -->真
B=arr+4 p=arr+4 -->假 最后结果:p=arr+5
A=arr+4 p=arr+5 -->真
p=0x7fff28547e20
0x7fff28547e30 0x7fff28547e34 0x7fff28547e20
*/
/*
printf 输出特性:
特性1:从后往前计算
特性2:++/-- 在后面,表示真结束;
++/--在前面,则表示假结束,需要将最后的结果输出
特性3:输出的表达式若为赋值操作,则为假结束
*/
}
示例4:
c
#include <stdio.h>
int main()
{
int x=10,y=20;
printf("%d %d %d %d %d %d %d %d\n",x=100,x++ + ++y,x+y,++x,y++,x++,++y,x+5);
/* B A C D E F G H
H=15 x=10
G=21 y=21 假
F=10 x=11
E=21 y=22
D=12 x=12 假
C=12+22=34
A=12+23=35 x=13 y=23
B=100
100 35 34 100 21 10 23 15
*/
int arr[]={12,34,6,87,98,200};
int *p=arr;
printf("arr=%p\n",arr);
printf("%p %p %d %d\n",p++,++p,*p,*p++);
/* A B C D
D=12 p=arr+1
C=34 p=arr+1
B=arr+2 p=arr+2 假 -->arr+3
A=arr+2 p=arr+3
arr+2 arr+3 34 12
arr=0x7fffdf4837f0
0x7fffdf4837f8 0x7fffdf4837fc 34 12
*/
}