
且看上面的诗歌水墨画,画中的诗词以一定的格式排版在山水画的上方,与山水融为一体 这便是格式化排版带来的效果,我们也可以将这个方法应用于我们的代码输出中,使我们输出的代码更加整齐规律
printf是C标准库中最核心的输出函数,其格式化功能极其丰富。
下面将分别从八个维度讲解
格式符 | 说明 | 对应数据类型 | 示例 |
|---|---|---|---|
%d | 有符号十进制整数 | int | printf("%d", 42) |
%i | 有符号十进制整数(同%d) | int | printf("%i", 42) |
%u | 无符号十进制整数 | unsigned int | printf("%u", 42u) |
%o | 无符号八进制整数 | unsigned int | printf("%o", 42) |
%x | 无符号十六进制(小写) | unsigned int | printf("%x", 255)→"ff" |
%X | 无符号十六进制(大写) | unsigned int | printf("%X", 255)→"FF" |
%hd | 短整型十进制 | short | printf("%hd", (short)42) |
%ld | 长整型十进制 | long | printf("%ld", 42L) |
%lld | 长长整型十进制 | long long | printf("%lld", 42LL) |
%zu | size_t类型无符号十进制 | size_t | printf("%zu", sizeof(int)) |
格式符 | 说明 | 对应数据类型 | 示例 |
|---|---|---|---|
%f | 十进制小数表示 | float/double | printf("%f", 3.14) |
%F | 同%f但INF/NAN大写 | float/double | printf("%F", INFINITY)→"INF" |
%e | 科学计数法(小写e) | float/double | printf("%e", 314.0)→"3.140000e+02" |
%E | 科学计数法(大写E) | float/double | printf("%E", 314.0)→"3.140000E+02" |
%g | 自动选择%f或%e(更紧凑) | float/double | printf("%g", 3.14000)→"3.14" |
%G | 自动选择%F或%E(大写) | float/double | printf("%G", 314.0)→"314" |
%a | 十六进制浮点(小写) | float/double(C99) | printf("%a", 3.14)→"0x1.91eb86p+1" |
%A | 十六进制浮点(大写) | float/double(C99) | printf("%A", 3.14)→"0X1.91EB86P+1" |
格式符 | 说明 | 对应数据类型 | 示例 |
|---|---|---|---|
%c | 单个字符 | char | printf("%c", 'A') |
%lc | 宽字符 | wchar_t | printf("%lc", L'中') |
%s | 字符串 | char* | printf("%s", "hello") |
%ls | 宽字符串 | wchar_t* | printf("%ls", L"中文") |
格式符 | 说明 | 对应数据类型 | 示例 |
|---|---|---|---|
%p | 指针地址(十六进制) | void* | printf("%p", &var)→"0x7ffeeb39a82c" |
%n | 存储已写字符数 | int* | int cnt; printf("123%n", &cnt);→cnt=3 |
printf("%10d", 123); // " 123"printf("%*[其他格式]", width_value, data);代码示例:
int w = 8;
printf("%*d", w, 123); // " 123"简单来讲就是在 C 语言的 printf 格式化输出中,宽度(width) 用于控制输出的最小占位宽度。其核心规则是:当数据实际宽度 ≥ 指定宽度时,按实际宽度输出;当数据实际宽度 < 指定宽度时,按指定宽度填充。
标志 | 作用 | 示例 | 输出示例 | 适用格式说明符 |
|---|---|---|---|---|
- | 左对齐 | %-10s | "Hello " | 所有数值和字符串格式 |
+ | 强制显示正负号 | %+d | "+123" | 有符号数值(d,i,f等) |
空格 | 正数前保留空格 | % d | " 123" | 有符号数值 |
# | 显示进制前缀 | %#x | "0x7b" | o,x,X,a,A,f,F,e,E,g,G |
0 | 用零填充数字宽度 | %08d | "00000123" | 所有数值格式 |
%+-10d 表示左对齐、显示符号、宽度100 和 - 同时存在时,- 会覆盖 0(如 %-08d 会按左对齐用空格填充)# 在浮点数中会强制输出小数点(即使没有小数部分)# 在 g/G 格式中会保留尾随的零+ 和空格对无符号数(u,o,x)无效0 对字符串(s)无效printf("%.5d", 123); // "00123"(前导零)printf("%.2f", 3.14159); // "3.14"printf("%.5s", "HelloWorld"); // "Hello"int p = 3;
printf("%.*f", p, 3.14159); // "3.142"修饰符 | 适用类型 | 说明 | 示例 | 输出示例(假设值为42) |
|---|---|---|---|---|
hh | char | 有符号字符型 | printf("%hhd", c) | 42 |
h | short | 短整型 | printf("%hd", s) | 42 |
l | long | 长整型 | printf("%ld", l) | 42 |
ll | long long | 长长整型 | printf("%lld", ll) | 42 |
L | long double | 长双精度浮点 | printf("%Lf", ld) | 42.000000 |
z | size_t | 大小类型(无符号) | printf("%zu", sz) | 42 |
t | ptrdiff_t | 指针差值类型 | printf("%td", pt) | 42 |
j | intmax_t | 最大宽度整数类型 | printf("%jd", j) | 42 |
组合规则:
%ld对应long,%lf对应double)L专用于long double(如%Lf)平台差异:
// 32位系统:long=4字节,64位系统:long=8字节
printf("%ld", sizeof(long)); printf("%%"); // "%"printf("%'d", 1234567); // "1,234,567"(依赖locale)格式说明符 | 合法输入类型 | 非法输入类型 | 风险等级 | 典型错误示例 |
|---|---|---|---|---|
%d | int, char, short | float, long | 高 | printf("%d", 3.14f); |
%ld | long | int, double | 中 | printf("%ld", 42); |
%lld | long long | int, float | 高 | printf("%lld", 100); |
%u | unsigned int | float, 指针 | 高 | printf("%u", -1); |
%f | double, float | int, long | 高 | printf("%f", 42); |
%Lf | long double | double, int | 高 | printf("%Lf", 3.14); |
%p | 任何指针类型 | 非指针类型 | 高 | printf("%p", 123); |
%s | char* (NUL结尾) | int, float | 崩溃风险 | printf("%s", 0x1234); |
%c | int (0-255), char | float, char* | 中 | printf("%c", "A"); |
%x/%X | unsigned int | 有符号整数 | 中 | printf("%x", -1); |
使用静态分析工具检查格式字符串:
gcc -Wformat -Wformat-security在格式字符串中使用 %n$ 指定参数位置(n从1开始):
printf("%2$d %1$d", a, b); // 先输出b,再输出a特性 | 说明 | 示例 | 输出示例(假设参数为"Hello", 123) |
|---|---|---|---|
位置指定 | 通过%n$指定参数位置(n从1开始) | printf("%2$s %1$d", 123, "Hello") | "Hello 123" |
混合使用 | 可与普通格式说明符混合使用 | printf("%s %2$d", "Num:", 42) | "Num: 42" |
重复使用 | 单个参数可被多次引用 | printf("%1$s %1$s", "Hi") | "Hi Hi" |
动态宽度 | 结合*实现动态宽度/精度 | printf("%1$*2$d", 5, 8) | " 5"(宽度8) |
顺序重置 | 使用%n$后后续参数需重新编号 | printf("%2$d %d", 1, 2) | "2 1"(第二个%d复用第1个参数) |
希望通过这八个维度能够让大家更好去了解printf的输出方法
看到这里麻烦给个三连支持一下小编