- gf25030 的博客
printf
- @ 2026-5-29 20:01:54
C++ printf 完全指南:从入门到精通
前言
尽管 C++ 提供了 cout 进行输出,但 printf 凭借其格式化的灵活性和高效性,仍然是许多场景下的首选。本文将全面介绍 printf 的用法。
1. 基本语法
#include <cstdio> // C++ 中使用 cstdio,C语言使用 stdio.h
int printf(const char* format, ...);
2. 格式说明符
2.1 常用格式符
| 格式符 | 类型 | 示例 |
|---|---|---|
%d |
int | printf("%d", 123); |
%ld |
long | printf("%ld", 123456L); |
%lld |
long long | printf("%lld", 123456789LL); |
%u |
unsigned int | printf("%u", 123U); |
%f |
float/double | printf("%f", 3.14); |
%lf |
double | printf("%lf", 3.14159); |
%c |
char | printf("%c", 'A'); |
%s |
字符串(char*) | printf("%s", "Hello"); |
%p |
指针 | printf("%p", ptr); |
%x / %X |
十六进制 | printf("%x", 255); // ff |
%o |
八进制 | printf("%o", 8); // 10 |
%% |
百分号 | printf("%%"); // % |
2.2 修饰符
// 宽度和精度
printf("%10d", 123); // 宽度10,右对齐
printf("%-10d", 123); // 左对齐
printf("%010d", 123); // 宽度10,前导零填充
printf("%.2f", 3.14159); // 保留2位小数
printf("%8.3f", 3.14); // 宽度8,精度3
// 不同进制
printf("%#x", 255); // 0xff
printf("%#o", 8); // 010
3. 实际示例
3.1 基础输出
#include <cstdio>
int main() {
// 整数输出
printf("整数: %d\n", 42);
printf("十六进制: %x | 大写: %X\n", 255, 255);
// 浮点数
printf("浮点数: %f\n", 3.14159);
printf("保留2位: %.2f\n", 3.14159);
// 字符和字符串
printf("字符: %c\n", 'A');
printf("字符串: %s\n", "Hello C++");
// 指针
int x = 10;
printf("指针地址: %p\n", &x);
return 0;
}
3.2 格式化对齐
#include <cstdio>
int main() {
printf("右对齐:\n");
printf("%10s | %10s\n", "Name", "Score");
printf("%10s | %10d\n", "Alice", 95);
printf("%10s | %10d\n", "Bob", 87);
printf("\n左对齐:\n");
printf("%-10s | %-10s\n", "Name", "Score");
printf("%-10s | %-10d\n", "Alice", 95);
printf("%-10s | %-10d\n", "Bob", 87);
return 0;
}
3.3 多变量输出
#include <cstdio>
int main() {
int age = 25;
double height = 1.75;
char grade = 'A';
printf("年龄: %d, 身高: %.2f, 等级: %c\n",
age, height, grade);
// 混合格式
printf("十进制: %d | 八进制: %o | 十六进制: %x\n",
100, 100, 100);
return 0;
}
4. 返回值
#include <cstdio>
int main() {
int count = printf("Hello %s\n", "World");
printf("输出了 %d 个字符\n", count);
// 输出: Hello World
// 输出了 12 个字符
return 0;
}
5. 常见陷阱与注意事项
5.1 类型不匹配
// ❌ 错误示例
long long big = 123456789LL;
printf("%d", big); // 错误!应该用 %lld
// ✅ 正确示例
printf("%lld", big);
5.2 浮点数精度
double pi = 3.14159265358979;
printf("%.10f\n", pi); // 3.1415926536 (四舍五入)
printf("%.15f\n", pi); // 3.141592653589790
5.3 字符串安全
// ⚠️ 危险:可能导致缓冲区溢出
char buffer[10];
sprintf(buffer, "%s", "This string is too long!");
// ✅ 安全:限制长度
snprintf(buffer, sizeof(buffer), "%s", "This string is too long!");
6. 高级技巧
6.1 动态宽度和精度
#include <cstdio>
int main() {
int width = 10;
int precision = 3;
double value = 3.14159;
// 使用 * 动态指定
printf("%*.*f\n", width, precision, value);
// 等价于: printf("%10.3f\n", value);
return 0;
}
6.2 printf 与 C++ 混用
#include <iostream>
#include <cstdio>
int main() {
std::cout << "C++输出: ";
printf("C风格输出\n");
// 注意:混用可能导致顺序问题
std::cout << "Hello ";
printf("World");
std::cout << " C++" << std::endl;
// 可能输出: Hello World C++
return 0;
}
7. 性能对比
#include <cstdio>
#include <iostream>
#include <chrono>
int main() {
const int N = 100000;
// printf 测试
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < N; i++) {
printf("%d ", i);
}
auto end = std::chrono::high_resolution_clock::now();
auto printf_time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
// cout 测试
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < N; i++) {
std::cout << i << " ";
}
end = std::chrono::high_resolution_clock::now();
auto cout_time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
printf("\nprintf耗时: %lld ms\n", printf_time.count());
printf("cout耗时: %lld ms\n", cout_time.count());
return 0;
}
8. 快速参考卡片
// 整数
%d // int
%ld // long
%lld // long long
%u // unsigned int
%lu // unsigned long
// 浮点数
%f // float/double
%lf // double
%.2f // 保留2位小数
%g // 自动选择%f或%e
// 其他
%c // 字符
%s // 字符串
%p // 指针
%% // 百分号
// 格式控制
%-10s // 左对齐宽度10
%10d // 右对齐宽度10
%05d // 宽度5,前导零
%#x // 显示0x前缀
结语
printf 是一个强大且灵活的输出函数,掌握它能让你在 C++ 编程中更加得心应手。记住选择合适的格式说明符,注意类型匹配,就能避免大多数问题。
参考资料