基础
Hello World
老规矩我们还是先来看一下在C语言里是怎么写 Hello World 的:
1 |
|
其中:
#include <stdio.h>:引入标准输入输出库,printf就在这里面定义。include的部分一般被叫做头文件。
int main():程序的主函数,是程序执行的起点。printf("Hello, World!\n");:向屏幕输出Hello, World!,\n表示换行。return 0;:表示程序正常结束。
printf()
printf 是 C 标准库函数,用于格式化文本并将其输出到标准输出。
它的语法相比于其他的编程语言(比如说Python,C++之类的)会复杂很多。
printf的参数主要分成2部分:格式化字符串以及变量名。其中格式化字符串( format string)可以参考以下定义(我个人觉得这个定义比较清楚):
The format string is a character string which contains two types of objects: plain characters, which are simply copied to the output channel, and conversion specifications, each of which causes conversion and printing of arguments.
(来源:https://ocaml.org/manual/5.0/api/Printf.html)
我们来分情况看一下printf的具体语法:
1. 只有字符串的情况:
1 |
|
这种情况下就非常简单,直接在引号里输入希望输出的内容即可。
2. 涉及变量的情况:
1 |
|
我们需要在格式化字符串( format string)里给定符合要求的格式化。
格式化占位符的语法如下:
1 | %[parameter][flags][field width][.precision][length]type |
- Parameter:指定用于格式化的参数位置(从1开始)
| 字符 | 说明 |
|---|---|
n$ |
其中n是参数位置 |
例子:
1 | printf("%2$d %1$d", 11, 22); |
- Flags:
| 标志 | 说明 |
|---|---|
- |
左对齐(默认是右对齐) |
+ |
总是显示正号或负号(例如 +10) |
(空格) |
正数前加空格,负数前加负号 |
0 |
用0填充未占满的宽度 |
# |
对于%o、%x、%X等,添加前缀(如0x);对于%f等,始终包含小数点 |
- Field Width:指定最小输出字符数,不足时用空格(或0)填充,如果要使用变量指定宽度,可以用 *。
例子:
1 | printf("%d", 42); |
- Precision:指定数字小数点后的位数或字符串的最大输出长度:
- 对于浮点数(如
%f):表示小数点后保留的位数,如%.2f - 对于字符串(如
%s):表示最大输出字符数,如%.5s - 可以使用
*表示由参数动态提供
- Length:指出浮点型参数或整型参数的长度
| 修饰符 | 说明 |
|---|---|
hh |
signed char 或 unsigned char |
h |
short 或 unsigned short |
l |
long 或 unsigned long |
ll |
long long 或 unsigned long long |
L |
long double(用于%Lf) |
z |
size_t |
t |
ptrdiff_t |
j |
intmax_t 或 uintmax_t |
例子:
1 |
|
- Type:也称转换说明(conversion specification/specifier),指定具体的数据类型,有以下选择
| 字符 | 说明 |
|---|---|
%d |
打印十进制整数(int) |
| %f | 打印浮点数(float/double) |
| %.2f | 打印浮点数,保留小数点后2位 |
| %s | 打印字符串(char*) |
| %c | 打印单个字符(char) |
| %x | 打印十六进制(小写) |
| %% | 输出一个百分号 % |
其中只有Type是必须要给的,其他均可以省略。
例子:
1 |
|
注意:在第二部分一定要给定变量,如果没有给,则会从错误的内存地址读取数据,导致不可预期的行为。
此外还有一个比较特殊的格式符:%n 。这个格式符会让 printf 把当前已经打印的字符数量写入 n 所在的地址。
比如说下面这个例子
1 |
|
n的值会被存储为5。
由于它的特殊性以及危险性,很多现代系统在 libc 中禁用了 %n,或者在格式化函数上增加了保护(如 glibc 中对 %n 的格式检查)。