C.printf 函数基础
printf 函数
- 1. printf 函数基础
- 1.1 函数原型与头文件
- 1.2 格式化输出的基本概念
- 2.1 常见格式说明符
- 整数格式说明符
- 浮点数格式说明符
- 字符和字符串格式说明符
- 其他格式说明符
- 2.2 格式说明符的高级用法
- 宽度修饰符
- 精度修饰符
- 对齐修饰符
- 符号修饰符
- 填充修饰符
- 组合修饰符
- 3.1 宽度与对齐
- 宽度修饰符
- 对齐修饰符
- 实际应用示例
- 3.2 精度控制
- 浮点数精度
- 字符串精度
- 动态精度
- 实际应用示例
- 4.1 返回值的含义
- 4.2 返回值的应用场景
- 4.2.1 输出校验
- 4.2.2 动态调整输出
- 4.2.3 调试与日志记录
- 4.2.4 嵌套调用中的应用
- 5.1 格式化字符串漏洞
- 格式化字符串漏洞的成因
- 格式化字符串漏洞的利用
- 格式化字符串漏洞的实例
- 5.2 安全使用建议
- 1. 避免用户可控的格式化字符串
- 2. 确保格式说明符与参数匹配
- 3. 使用安全的格式化函数
- 4. 检查 `printf` 的返回值
- 5. 避免使用 `%n` 格式说明符
- 6. 使用编译器的安全检查功能
- 6.1 fprintf
- 使用场景
- 返回值
- 6.2 sprintf
- 使用场景
- 返回值
- 安全问题
- 6.3 snprintf
- 使用场景
- 返回值
- 安全性
- 7.1 日常编程中的使用场景
- 1. 输出调试信息
- 2. 输出用户友好的消息
- 3. 格式化输出数据
- 4. 输出表格数据
- 5. 输出日志信息
- 7.2 复杂格式化输出示例
- 1. 输出多行格式化数据
- 2. 动态格式化输出
- 3. 输出带有颜色的文本
- 4. 输出带有条件的文本
- 5. 输出带有时间戳的日志信息
1. printf 函数基础
1.1 函数原型与头文件
printf
函数是 C 语言中用于格式化输出的标准函数,其函数原型定义在头文件 <stdio.h>
中。具体原型如下:
int printf(const char *format, ...);
const char *format
:格式控制字符串,用于指定输出的格式。它由普通字符和格式说明符组成。普通字符将按原样输出,而格式说明符则用于指定后续参数的输出格式。...
:表示可变参数列表,这些参数将根据格式控制字符串中的格式说明符依次输出。
在使用 printf
函数时,必须包含头文件 <stdio.h>
,否则编译器将无法识别该函数。
1.2 格式化输出的基本概念
printf
函数通过格式控制字符串来实现灵活的输出。格式控制字符串中的格式说明符以 %
开头,后跟一个或多个字符,用于指定输出数据的类型和格式。以下是一些常见的格式说明符及其含义:
格式说明符 | 含义 |
---|---|
%d 或 %i | 输出有符号十进制整数。例如:printf("%d", 123); 输出 123 。 |
%u | 输出无符号十进制整数。例如:printf("%u", 456); 输出 456 。 |
%f | 输出浮点数,默认保留 6 位小数。例如:printf("%f", 3.14159); 输出 3.141590 。 |
%c | 输出单个字符。例如:printf("%c", 'A'); 输出 A 。 |
%s | 输出字符串。例如:printf("%s", "Hello"); 输出 Hello 。 |
%p | 输出指针地址。例如:printf("%p", &var); 输出变量 var 的地址。 |
%% | 输出一个百分号 % 。例如:printf("%%"); 输出 % 。 |
格式说明符还可以包含一些可选的修饰符,用于控制输出的宽度、精度、对齐方式等。以下是一些常见的修饰符及其用法:
-
宽度修饰符:指定输出的最小宽度。如果实际输出的宽度小于指定的宽度,则会在左侧或右侧填充空格(默认为右侧)。例如:
printf("%5d", 123); // 输出 " 123",总宽度为 5,左侧填充空格 printf("%-5d", 123); // 输出 "123 ",总宽度为 5,右侧填充空格
-
精度修饰符:对于浮点数,指定小数点后的位数;对于字符串,指定最大输出长度。例如:
printf("%.2f", 3.14159); // 输出 "3.14",小数点后保留 2 位 printf("%.3s", "Hello"); // 输出 "Hel",字符串的最大长度为 3
-
对齐修饰符:
-
用于左对齐,+
用于强制输出正负号,空格用于在正数前输出空格。例如:printf("%-5d", 123); // 输出 "123 ",左对齐 printf("%+d", 123); // 输出 "+123",强制输出正号 printf("% d", 123); // 输出 " 123",正数前输出空格
通过合理使用格式说明符和修饰符,printf
函数可以实现灵活多样的格式化输出,满足各种编程需求。# 2. 格式说明符详解
2.1 常见格式说明符
printf
函数的格式说明符是实现格式化输出的核心,以下是一些常见的格式说明符及其详细用法:
整数格式说明符
%d
或%i
:用于输出有符号十进制整数。这是最常用的整数格式说明符,适用于正负整数。printf("Value: %d\n", -123); // 输出:Value: -123
%u
:用于输出无符号十进制整数。它适用于非负整数,输出时不会显示负号。printf("Value: %u\n", 456); // 输出:Value: 456
%o
:用于输出无符号八进制整数。输出时不会显示前缀0
。printf("Octal: %o\n", 255); // 输出:Octal: 377
%x
或%X
:用于输出无符号十六进制整数。%x
输出小写字母,%X
输出大写字母。printf("Hex: %x\n", 255); // 输出:Hex: ff printf("Hex: %X\n", 255); // 输出:Hex: FF
浮点数格式说明符
%f
:用于输出十进制浮点数,默认保留 6 位小数。可以通过精度修饰符指定小数点后的位数。printf("Float: %f\n", 3.1415926); // 输出:Float: 3.141593 printf("Float: %.2f\n", 3.1415926); // 输出:Float: 3.14
%e
或%E
:用于输出科学计数法表示的浮点数。%e
输出小写字母e
,%E
输出大写字母E
。printf("Scientific: %e\n", 3.1415926); // 输出:Scientific: 3.141593e+00 printf("Scientific: %E\n", 3.1415926); // 输出:Scientific: 3.141593E+00
字符和字符串格式说明符
%c
:用于输出单个字符。printf("Char: %c\n", 'A'); // 输出:Char: A
%s
:用于输出字符串。可以通过精度修饰符指定最大输出长度。printf("String: %s\n", "Hello, World!"); // 输出:String: Hello, World! printf("String: %.5s\n", "Hello, World!"); // 输出:String: Hello
其他格式说明符
%p
:用于输出指针地址。int var = 10; printf("Address: %p\n", &var); // 输出指针地址
%%
:用于输出一个百分号%
。printf("Percentage: %%\n"); // 输出:Percentage: %
2.2 格式说明符的高级用法
格式说明符还可以结合多种修饰符来实现更复杂的格式化输出,以下是一些高级用法:
宽度修饰符
宽度修饰符用于指定输出的最小宽度。如果实际输出的宽度小于指定的宽度,则会在左侧或右侧填充空格(默认为右侧)。可以通过以下方式指定宽度:
- 固定宽度:直接指定一个整数。
printf("%10d\n", 123); // 输出: 123
- 动态宽度:使用
*
表示宽度由后续参数指定。int width = 10; printf("%*d\n", width, 123); // 输出: 123
精度修饰符
精度修饰符用于控制输出的精度,对于浮点数和字符串有不同的含义:
- 浮点数:指定小数点后的位数。
printf("%.*f\n", 3, 3.1415926); // 输出:3.142
- 字符串:指定最大输出长度。
printf("%.*s\n", 5, "Hello, World!"); // 输出:Hello
对齐修饰符
对齐修饰符用于控制输出的对齐方式:
- 左对齐:使用
-
修饰符。printf("%-10d\n", 123); // 输出:123
- 右对齐:默认对齐方式。
printf("%10d\n", 123); // 输出: 123
符号修饰符
符号修饰符用于控制输出的符号:
- 强制显示符号:使用
+
修饰符。printf("%+d\n"