C语言多个源代码文件的编译

在c和c++的linux系统编程项目中,项目中的文件经常被分为.h文件和.c文件,对于多个文件的编译我总是不太清楚,所以今天对linux系统中多个文件的编译进行一下总结,参考的课程是翁恺老师的c语言课程。

以下面简单的程序为例,刚开始所有函数都在一个文件中。

// test.cpp
#include <stdio.h>

int max(int a,int b);

int main(){
    int a=5;
    int b=6;
    printf("%d\n",max(a,b));
    return 0;
}

int max(int a,int b){
    return a>b ? a:b;
}

使用gcc对文件进行编译,显然没有什么问题。
在这里插入图片描述
现在把文件中的函数拿出来单独作为一个cpp文件。因此现在有了两个源文件max.cpp和main.cpp:

// max.cpp
int max(int a,int b){
    return a>b ? a:b;
}

// main.cpp
#include <stdio.h>

int max(int a,int b);

int main(){
    int a=5;
    int b=6;
    printf("%d\n",max(a,b));
    return 0;
}

将两个源文件一起编译,同样也没有问题。
在这里插入图片描述
不过注意到,main.cpp中有int max(int a,int b);这一句,这是对max()函数的声明,如果不加这句声明,这里我使用的vscode中,编译器就会出现报错提示:未定义标识符 "max"。当一个源文件中函数数量过多时,就需要将一个源文件拆分为多个源文件,因此函数声明就变成了项目中一个不可缺少的部分。

因此在这里就可以引入头文件和声明的关系了:

头文件的作用就是把函数原型放到一个头文件 (以.h结尾) 中,在需要调用这个函数的源代码文件 (c文件) 中#include这个头文件,就能让编译器在编译的时候知道函数的原型。
因此对于上面的代码,就可以把函数声明单独拿出来作为一个.h文件,在每个使用了max()函数以及定义max()函数的文件中都要#include这个头文件。在使用max()函数的文件中,函数声明告诉这个文件中的函数,max()函数是什么样的,而在定义max()函数的文件中,函数声明起到了一个检查的作用,来检查函数声明的形式和实际的max()函数定义是不是一致的,因此函数声明可以被看做是一个使函数建立联系的桥梁。

//max.h
#include "max.h"
int max(int a,int b);

// max.cpp
int max(int a,int b){
    return a>b ? a:b;
}

// main.cpp
#include <stdio.h>
#include "max.h"

int main(){
    int a=5;
    int b=6;
    printf("%d\n",max(a,b));
    return 0;
}

还是按照之前的老办法对.cpp文件进行编译,编译通过了。
在这里插入图片描述

顺便再介绍一下#include指令的作用以及头文件" "和< >的区别:
#include指令的作用:
1、#include是一个编译预处理指令,和宏一样,在编译之前就处理了。
2、它把那个文件的全部文本内容原封不动地插入到它所在的地方。
3、所以也不是一定要在c文件的最前面#include

头文件" "和< >的区别:
#include有两种形式来指出要插入的文件
1、“ ”要求编译器首先在当前目录 (c文件所在的目录)寻找这个文件,如果没有,到编译器指定的目录去
2、< >让编译器只在指定的目录去找
3、编译器自己知道自己的标准库的头文件在哪里环境变量和编译器命令行参数也可以指定寻找头文件的目录

#include的误区
1、#include不是用来引入库的
2、stdio.h里只有printf的原型,printf的代码在另外的地方,某个.lib(Windows)或.a(Unix)中
3、现在的C语言编译器默认会引入所有的标准库,但是编译c++程序的时候最好用g++编译器,用gcc编译器有时候会出现找不到标准库,需要自己手动链接的问题。
4、#include <stdio.h>只是为了让编译器知道printf函数的原型,保证你调用时给出的参数值是正确的类型

头文件
1、在使用和定义这个函数的地方都应该#include这个头文件
2、一般的做法就是任何.c都有对应的同名的.h,把所有对外公开的函数的原型全局变量的声明都放进去。(全局变量也是可以在多个源文件之间共享的)。
3.为了防止头文件中的内容被重复#include,即同一个编译单元当中同名结构被声明多次,这会造成错误,因此需要使用标准头文件结构。
在这里插入图片描述

不对外公开的函数
1、在函数前面加上static就使得它成为只能在所在的编译单元中被使用的函数
2、在全局变量前面加上static就使得它成为只能在所在的编译单元中被使用的全局变量

  • 24
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值