1.多个 .c文件,如何编译
- main()里的代码太长,适合分成几个函数
- 一个源代码文件太长,适合分成几个文件
- 两个独立的源代码文件 不能编译成一个可执行程序
之前我们写的代码,是放在一个.c文件中,如果main写在一个.c文件中,max()写在一个.c文件中呢?
2.项目
- 新建项目: Devcpp中 文件 —— 新建 —— 项目 —— Console Application
- 对于项目,Devcpp 的编译会把一个项目中的所有源代码文件都编译后,链接起来
- 有的IDE有 编译 和 构建 两个按钮,编译 是对单个源代码文件编译,构建是对整个项目做链接
3.编译单元
- 一个.c文件就是一个编译单元
- 编译器每次编译只处理一个编译单元
4.头文件
把函数原型 放到一个 以.h结尾的头文件中,在需要调用这个函数的 .c 源代码文件中 #include这个头文件,编译器在编译的时候就知道函数的原型了
新建——源代码——max.h
max.h
double max(double a,double b);
max.c
#include "max.h"
double max(double a,double b)
{
return a > b ? a : b;
}
main.c
#include <stdio.h>
#include "max.h"
int main(void) {
double a = 5;
double b = 6;
printf("max is %f\n", max(5, 6)); // max is 6.000000
return 0;
}
5.#include
- #include是一个编译预处理命令,和宏一样,在编译之前就处理了
- 编译时,把头文件的全部文本内容 原封不动地 插入到 include所在的地方
5.1 “” 还是 <>
- #include 有两种形式来指出要插入的文件
- ”“编译时,编译器首先在当前目录(.c文件所在的目录)寻找这个文件,如果没有 就到指定目录去找
- <>编译时,编译器只在指定的目录去找
- 编译器知道标准库的头文件在哪里
- 环境变量 和 编译器命令行参数 也可以指令头文件的目录
5.2 误区
- #include 不是用来引入库的
- 现在的C语言编译器默认会引入所有的标准库
#include <stdio.h> 只是为了让编译器知道 printf函数的原型,保证你调用时给出的参数值是正确的类型
stdio.h 里只有printf()的原型,printf的代码在另外的某个 .lib(Windows)或.a(Unix)中
6 头文件
- 一般的做法是 任何 .c 都有对应的同名的.h,把所有对外公开的函数原型 和 全局变量的生命 都放进去
- 在使用 和 定义 这个函数的地方都应该 #include 这个头文件
7.声明
7.1 声明与定义
int i; // 变量的定义
extern int i; // 变量的声明
- 声明是不产生代码的
- 函数原型
- 变量原型
- 结构声明
- 宏声明
- 枚举声明
- 类型声明
- inline函数
- 定义是产生代码的
7.2 声明的使用
- 只有声明可以放在头文件中(是规则不是法律)
- 否则会造成一个项目中多个编译单元里有重名的实体
- 某些编译器允许几个编译单元中存在同名的函数,或者用weak修饰符来强调这种存在
7.3 重复声明
- 同一个编译单元里,同名的结构不能被重复声明
- 如果头文件里有 结构的声明,很难保证 这个头文件 不会在一个编译单元里 被#include多次
- 需要“标准头文件结构”
- 运用条件编译和宏,保证这个头文件在一个编译单元中只会被#include一次
- #pragma once 也能起到相同的作用,但是不是所有的编译器都支持
错误示例:
struct Node{
int value;
char* name;
};
// [Error] redefinition of 'struct Node' 重新定义 struct Node
struct Node{
int value;
char* name;
};
int main(void) {
return 0;
}
标准写法:
max.h
#ifndef _MAX_H_
#define _MAX_H_
double max(double a,double b);
extern int gAll;
struct Node{
int value;
char* name;
};
#endif
max.c
#include <stdio.h>
#include "max.h"
int gAll = 12;
int main(void) {
double a = 5;
double b = 6;
printf("max is %f\n", max(5, 6)); // max is 6.000000
return 0;
}
max.c
#include "max.h"
double max(double a,double b)
{
return a > b ? a : b;
}