一、 多个源代码文件
- 多个源代码文件需要在同一个项目文件目录之下;
- 多个源代码文件需要先单独编译,然后将整个项目中的文件链接起来(VS需要“编译”(compile) - “构建”(build))。每一个
.c
文件都是一个编译单元,编译器每次只能处理一个编译单元。 - 编译
.c
文件将产生.o
的目标文件,然后构建产生.exe
文件。
二、 头文件
2.1 头文件
- 将函数原型放到头文件(
.h
)中。在需要调用该函数的源代码文件(.c
)中#include
其所在的头文件,以便让编译器在编译的时候知道该函数的原型。避免因数据类型不统一而出现错误。 - 将函数原型放入创建的头文件中,则在实际需要调用该函数的源代码文件的开头写函数原型,只需要 include 所在的头文件即可,这对需要调用大量函数的情况尤其方便。
2.2 include
指令
#include
为编译预处理指令,会在编译之前将相应头文件的全部文本内容原封不动地插入到该指令所在的位置。#include
文件有两种插入形式:"文件名"
—— 要求编译器首先在当前目录(.c
文件所在目录)寻找此文件,若没有,就到编译器指定的目录里去找;<文件名>
—— 要求编译器只在指定的目录里去找。
- 编译器知道自己的标准库的头文件所在位置,环境变量和编译器命令行也可以指定寻找头文件的目录。
stdio.h
里只有函数的原型,例如printf
函数的原型,其内部不含有函数的源代码,而在某个.lib
(Windows系统)或.a
(Unix系统)之中。- 现在的C语言编译器默认会引入所有的标准库。
- 在使用和定义某个函数的位置都应该 #include 其所在的头文件。一般是任何 .c 都应该有对应的同名 .h 文件,把所有岁外公开的函数的原型和全局变量的声明都放进去。(全局变量具有文件作用域,可以在多个 .c 文件之间共享。)
- 在函数前面加上
static
使得其成为所在编译单元的专用的函数(局部函数),其他 .c 文件不得使用该函数。 - 在全局变量前面加上
static
使得其成为所在文件的专用全局变量(局部全局变量),其他地方不得使用。
三、 声明
3.1 声明
在头文件中存储extern int gAll;
语句,使得在同一项目内,跨.c
文件调用全局变量 gAll 。在需要调用 gAll 的文件内 include 含有该语句的头文件。
-
int i;
是变量的定义; -
extern int i;
是变量的声明。 -
(在C语言中,定义和声明不一样,例如函数原型是声明,函数定义是定义)
-
在C语言中,声明是不产生代码的东西:
- 函数原型;
- 变量声明;
- 结构声明;
- 宏声明;
- 枚举声明;
- inline函数
-
定义是产生代码的东西。
注意:
- 只有声明才能放在头文件中,定义不得放入头文件。
- 在同一编译单元里(
.c
文件里),同名结构不能被重复声明;
3.2 标准头文件结构
#ifndef __LIST_HEAD__ //如果未定义
#define __LIST_HEAD__ //则定义
#include "node.h"
typedef struct _list {
Node* head;
Node* tail;
} List;
#endif //结束
- 运用条件编译和宏,保证这个头问价在一个编译单元中只会被 #include 一次,避免重复声明。
- #pragma once 也能起到相同的作用,但不是所有的编译器都支持。
四、 格式化输入输出
4.1 printf
- %[flags][width][.prec][hlL]type
4.1.1 flag
Flag | 含义 |
---|---|
- | 左对齐 |
+ | 在前面放 + (正数)或 -(负数) |
(space) | 正数留空 |
0 | (左侧)0填充 |
printf("%-9d\n", 123); //左对齐
printf("%9d\n", 123); //默认右对齐
printf("%+-9d\n", 123); //强制显示正负号,等价于%-+9d
printf("%+-9d\n", -123); //强制显示正负号
printf("%09d\n", 123); //左侧0填充
输出结果:
4.1.2 width 或 prec
width 或 prec | 含义 |
---|---|
number | (整个输出所占据的)最小字符数 |
* | 下一个参数是输出字符数 |
.number | 小数点后的位数 |
.* | 下一个参数时小数点后的数 |
printf("%*d\n",9, 123); //等价于%6d
printf("%9.2f\n", 123.0); //总共至少输出9位,保留2位小数
printf("%9.*f\n",2, 123.0); //等价于%9.2f
输出结果:
4.1.3 hlL
修饰类型 | 含义 |
---|---|
hh | 单个字节 |
h | short |
I | long |
ll | long long |
L | long double |
printf("%hhd\n", 12345); //12345(10) = 0x3039(H)
printf("%9.2f\n", 123.0);
输出结果:
输出说明:
12345(10) = 0x3039(H),按单字节输出,取最后的39,则0x39(H) = 57(10)
4.1.4 类型type
type | 用于 | type | 用于 |
---|---|---|---|
i 或 d | int | g | float |
u | unsigned int | G | float |
o | 八进制 | a或A | 十六进制浮点 |
x | 十六进制 | c | char |
X | 字母大写的十六进制 | s | 字符串 |
f 或 F | float, 6位小数 | P | 指针 | </