01. printf()的核心功能
作用:将 格式化数据 输出到 标准输出(stdout),支持多种数据类型和格式控制。
int printf(const char *format, ...);
- 参数:
format
:格式字符串,字符串或%
开头格式符...
:可变参数,与" "
内格式一一对应
- 返回值:成功返回输出的字符数,失败返回负数
eg:
int count = printf("Hello, %s!\n", "World");
printf("输出了 %d 个字符\n", count); // 输出:输出了 13 个字符
02. printf()格式说明符
常用格式符:
格式符 | 数据类型 | 示例 |
---|---|---|
%d | int | printf(“%d”, 66); |
%u | unsigned int | printf(“%u”, 66); |
%f | float/double | printf(“%.2f”, 6.666); |
%c | char | printf(“%c”, ‘A’); |
%s | 字符串 | printf(“%s”, “hello world”); |
%p | 指针地址 | printf(“%p”, &x); |
%zu | size_t | printf(“%zu”, 100); |
%x | 十六进制整数 | printf(“%x”, 66); |
格式控制:
默认右对齐,使用-
可左对齐输出。%m.ns
表示向右对齐占m列,左边不足补空格,输出字符只占n位,超出n位删去。同理%m.nf
亦是如此。
-
填充与对齐:
printf("%5d", 10); // " 10"。从右开始输出,不足处补空格 printf("%-5d", 10); // "10 "。从左开始输出,不足处补空格 printf("%05d", 7); // "00007"。从右开始输出,不足处补0
-
精度控制:
printf("%.3f", 3.14159); // "3.142"。保留3位小数 printf("%.6s", "hello world"); // 输出前6个字符 "hello "
03. printf() 的参数入栈顺序
C标准未规定参数求值顺序。大多数编译(GCC、Clang)默认从右往左入栈顺序,这样可以支持…可变参数。这里讨论常见情况。
注意: 不同编译器可能出现不同的结果。
示例代码:
int i = 1;
printf("%d, %d, %d\n", i++, i++, i++);
//GCC 一般情况输出 3, 2, 1
验证入栈顺序:
Linux下:
&a > &b > &c
符合栈的生长方向。
- 参数入栈顺序:从右到左(
c→b→a→格式串
),但 64位系统优先用寄存器(前6个参数通过rdi, rsi, rdx, rcx, r8, r9
传递)。 - 参数访问顺序:
printf
按格式字符串的%
顺序 从左到右 从寄存器或栈中读取参数。
参数传递:
rdi
= 格式字符串地址rsi
=a
的值 (10)rdx
=b
的值 (20)rcx
=c
的值 (30)
输出顺序:
printf
按 %p
顺序读取 rsi→rdx→rcx
,因此输出 &a, &b, &c
。
03. printf()输出流程
04. 缓冲区机制
- 行缓冲:默认模式(终端输出),遇到
\n
或缓冲区满时刷新。 - 全缓冲:文件输出,缓冲区满或调用
fflush
时刷新。 - 无缓冲:如
stderr
,立即输出。
2. 强制刷新示例
printf("Processing..."); // 无换行符,行缓冲下不会立即显示
fflush(stdout); // 强制刷新到屏幕