多个源代码文件

在设计大程序时,不可能将所有的代码都写在 main.c 中,一般将一个程序拆分成多个 .c 文件.可以使用下面命令将多个 .c 文件编译成一个可执行程序:

gcc main.c [xxx.c yyy.c zzz.c] [-o] [output]

如果使用ide集成开发环境,一般会有项目,编译时会将项目中的 .c 文件编译成一个可执行程序.

头文件

头文件

我们将多个 .c 文件编译成一个可执行程序时.并不是将其他.c文件插入到 main.c 的某一个部位.所以 main.c 在使用其他 .c 文件中的函数时,需要在开头声明一下函数原型.

如果不声明函数原型,但是你对函数参数的传入和结果的传出使用正确的话,也不会出现问题.但是一旦使用错误,就会出现问题.

此时就需要用到头文件了,头文件的后缀为 .h .我们可以使用 #include 来插入一个头文件.

#include <stdlib.h>
#include "node.h"
  • <> 引入头文件,会在系统特定的目录找这个头文件.一般用于引入标准库的头文件.
  • "" 引入头文件,会先在当前目录寻找这个头文件,找不到时再去系统特定目录寻找,一般用于引入自己写的头文件.

头文件中一般包含了这些函数的函数原型(并不包含函数本身,如果你想也可以,但一般不这么做).在编译预处理时,编译器会把头文件插入在引入头文件的位置.这样就不用在 main.c 中声明函数原型了.

关于#include的一个误区

  • #include 不是用来引入函数库的

  • stdio.h 里只有 printf 的函数原型, printf 的函数写在别的地方

  • C语言编译器会默认引入所有的标准库

  • #include<stdio.h> 只是为了让编译器知道 printf 的函数原型,确保在调用时给出的参数值是正确的类型

在学这节之前,我也一直认为 #include 是引入一个函数库o(╥﹏╥)o

局部函数

如果希望一个 .c 文件中的某一个函数,只能在该 .c 中使用. 需要在函数定义的开头加 static 来修饰. 此时这个函数可以看做一个局部函数,只在他所在的 .c 文件中生效.

声明

声明有很多种, 可以使用 extern 来声明一个变量.

int i; // 变量的定义
extern int i; // 变量的声明

这个关系有点像函数的定义和函数原型的声明. 同样,如果想在 main.c 中使用一个其他 .c 文件的全局变量,就需要声明一下.

  • 声明不会产生代码.

  • 定义会产生代码.

头文件

  • 只有声明可以写在头文件中.这是一个约定俗成的规矩,并不强制.
  • 如果在头文件中写定义,可能会导致同一实体被重复定义.或者出现同名的定义.
    • 某些编译器允许多个编译单元中有同名函数的存在,或者用 weak 修饰符强调这种存在.

重复声明

  • 同一个编译单元中,同名的结构不能被重复声明.
  • 如果头文件中声明了一个结构,这个结构很可能会被重复声明导致程序出错.
  • 我们可以用 "标准头文件结构" 来避免这种情况发生.

标准头文件结构:

/*
    如果这个头文件被引用过一次,___XXX___就会被定义,下一次重复引用时,直接跳到#endif,中间的代码就不会被引用了.
*/
#ifndef __XXX__ // 如果没有定义__XXX___
#define __XXX__ // 定义___XXX___
..CODE..
#endif

这样就可以保证一个头文件只会被引用一次..

最后修改:2023 年 04 月 28 日
如果觉得我的文章对你有用,请随意赞赏