基础
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
的格式检查)。