C语言学习(三)——格式转换说明符(printf / scanf 核心详解)
2025–2026 实用版(面试 + 实际开发最常踩坑点)
格式转换说明符(format specifier)是 printf、scanf、sprintf、sscanf 等系列函数的核心,写错一个字符就可能导致程序崩溃、输出乱码、未定义行为。
1. 最常用格式说明符速查表(必须背熟)
| 格式符 | 数据类型(C语言) | 典型用法示例 | 说明 / 常见变体 | 踩坑指数 |
|---|---|---|---|---|
%d 或 %i | int / signed int | printf("%d", 42); | 十进制有符号整数 | ★ |
%u | unsigned int | printf("%u", 4294967295u); | 十进制无符号整数 | ★★ |
%ld | long | printf("%ld", 1234567890L); | long 有符号(注意:long 可能是 32 或 64 位) | ★★★ |
%lu | unsigned long | printf("%lu", 1UL<<40); | long 无符号 | ★★★ |
%lld | long long | printf("%lld", 1LL<<60); | long long 有符号(64位) | ★★★★ |
%llu | unsigned long long | printf("%llu", ~0ULL); | long long 无符号 | ★★★★ |
%f | float / double | printf("%f", 3.14159); | 默认小数点后6位 | ★★ |
%e / %E | float / double | printf("%e", 0.000123); | 科学计数法 | ★★ |
%g / %G | float / double | printf("%g", 1234567.89); | 自动选择 %f 或 %e(简洁) | ★★ |
%c | char / int | printf("%c", 'A'); | 单个字符(传入 int 也会输出对应字符) | ★★ |
%s | char* / const char* | printf("%s", "hello"); | 字符串(以 \0 结尾) | ★★★★ |
%p | void* | printf("%p", (void*)&x); | 指针地址(通常带 0x 前缀) | ★★★ |
%% | 无 | printf("%%"); | 输出一个 % 符号 | ★ |
2. 长度修饰符(length modifier)完整对照表(最容易错的地方)
| 长度修饰符 | 对应类型(printf) | 对应类型(scanf) | 备注(64位系统常见情况) |
|---|---|---|---|
| (无) | int | int | 默认 32 位 |
h | short int | short int | 16 位 |
hh | signed char / unsigned char | signed char / unsigned char | 8 位 |
l | long | long | 32 或 64 位(平台相关,Windows 32位) |
ll | long long | long long | 固定 64 位(最常用) |
z | size_t / ssize_t | size_t / ssize_t | 指针大小相关(推荐用于 sizeof、strlen) |
t | ptrdiff_t | ptrdiff_t | 指针差值类型 |
j | intmax_t / uintmax_t | intmax_t / uintmax_t | 最大整数类型() |
高频组合记忆口诀(面试/写代码必备):
- 普通 int →
%d - unsigned int →
%u - long long →
%lld/%llu - size_t(数组长度、strlen返回值)→
%zu - 指针地址 →
%p(不要用%x或%lx) - 64位整数(无论 signed/unsigned)→ 一律用
ll修饰符
3. 宽度、精度、对齐(最常被问的格式控制)
格式:%[flags][width][.precision][length]specifier
| 部分 | 写法示例 | 含义 | 默认行为 |
|---|---|---|---|
| flags | - | 左对齐 | 默认右对齐 |
+ | 正数强制显示 + 号 | 只对负数显示 – | |
| (空格) | 正数前加空格 | — | |
0 | 用 0 填充(而不是空格) | 只对数字有效 | |
| width | 5 / * | 最小字段宽度(* 表示从参数读取) | 不足时右填充空格 |
| .precision | .2 / .* | 小数点后位数 / 字符串最大长度 | float 默认 6 位 |
| 示例汇总 | %8.2f | 总宽度8位,小数点后2位,右对齐 | 如:12.34 |
%-10s | 字符串左对齐,占10位 | 如:hello | |
%+010d | 带符号,宽度10,用0填充 | 如:+000001234 |
4. scanf 专用 & 容易出错的写法
| scanf 格式符 | 对应 C 类型 | 常见错误写法 | 正确写法 | 说明 |
|---|---|---|---|---|
%d %f %c | int float char | scanf("%d%f%c", &a, &b, &c); | 基本同 printf,但 char 要 & | — |
%s | char 数组 | scanf("%s", str); | 必须确保数组够大,否则溢出 | 遇到空格停止 |
%[^\n] 或 %[^\n]%*c | 整行读取(含空格) | scanf("%[^\n]", str); | 常用于读整行(包括空格) | 危险,建议用 fgets |
%zu | size_t | scanf("%u", &len); | scanf("%zu", &len); | 推荐 |
%lld | long long | scanf("%ld", &x); | scanf("%lld", &x); | 必须 ll |
5. 2025–2026 高频面试 / 笔试题型(附参考答案)
printf("%d", 1.5);输出什么?
→ 未定义行为(通常输出 0 或垃圾值)- 如何安全打印 size_t 类型?
→printf("%zu\n", sizeof(int)); - 下面代码有问题吗?
long long x = 123456789012345LL;
printf("%d\n", x);
→ 有问题!应该用 %lld
- 想输出类似
3.14(右对齐,宽度8,小数2位)怎么写?
→printf("%8.2f\n", 3.14); - 如何用 printf 输出 16 进制地址,但不要 0x 前缀?
→printf("%#x\n", (unsigned int)ptr);(带 0x)
→printf("%x\n", (unsigned int)ptr);(不带)
6. 推荐记忆口诀(快速背诵版)
- int 家族:d i u → ld lu → lld llu
- 浮点:f e g(默认6位小数)
- 字符/字符串:c s
- 指针:p(别用 x)
- size_t / ptrdiff_t:永远用 z / t
- 宽度精度:数字.数字
- 对齐:- 左对齐,0 补0,+ 强制正号
需要我针对某个具体场景(比如:精确控制小数位数、处理大整数、scanf 安全读行、sprintf 格式化到缓冲区等)再展开详细示例代码,或者出一套小练习题帮你巩固?直接告诉我~