C语言 15 预处理

C 语言学习已经快要接近尾声了,但是有一个东西迟迟还没有介绍,就是一直在写的:

c 复制代码
#include <stdio.h>

这到底是个什么东西,为什么每次都要加上呢?这里将详细讨论它缘由。

C 语言中带 # 号的指令并不是 C 关键字的一部分,不属于 C 语言。

带 # 号的指令是写给编译器看的,告诉它一些事情,好让它更好的为 C 代码服务。

比如 #include</font> 指令就是告诉编译器看到这句话就要把我写的文件包含进来,#define 指令就是告诉编译器看到这个宏就用前面已经定义好的内容替换。

文件包含

当预处理器发现#include指令时,会查看后面的文件名并把文件的内容包含到当前文件中,来替换掉#include指令。比如:

c 复制代码
int main() {
    printf("Hello World!");
}

这个函数是由系统提供的函数,实际上这个函数是在其他源文件中定义好的,而定义这个函数的源文件,就是stdio.h,可以点进去看看:

除了printf之外,看到还有很多很多的函数原型定义,他们都写到这个源文件中,而这个文件并不是以.c结尾的,而是以.h结尾的,这种文件称为头文件。头文件一般仅包含定义一类的简单信息,只要能让编译器认识就行了。

而#include则是将这些头文件中提供的信息包含到 C 语言源文件中,这样才能使用定义好的printf函数,如果不添加这个指令的话,那么会:

直接不认识了,如果不告诉编译器这个函数是从哪来的,它怎么知道这个函数的具体定义是什么,程序又该怎么执行呢?

#include的具体使用格式如下:

c 复制代码
#include <文件名称>

当然也可以写成:

plain 复制代码
#include "文件名称"

这两种写法虽然都能引入头文件,但是区别还是有的:

  • 尖括号: 引用的是编译器的库路径里面的头文件。
  • 双引号: 引用的是程序目录中相对路径中的头文件,如果找不到再去上面的库里面找。

可以看到系统已经提供好了多种多样的头文件了,通过这些系统提供的库,就可以做很多的事情了。

当然也可以自己编写一个头文件,直接在项目根目录下创建一个新的 C/C++ 头文件 test.h:

c 复制代码
// 声明函数原型
int test(int a, int b);

接着就可以编写源文件 test.c 引入这个头文件了:

c 复制代码
#include <stdio.h>
// 因为是自己项目目录中的,所以需要使用双引号
#include "test.h" 

int main() {
    // 这样就可以使用头文件中声明的函数了
    int c = test(1, 2);
    printf("%d", c);
}

// 编写函数具体实现
int test(int a, int b) {   
    return a + b;
}
c 复制代码
3

实际上预处理器正是通过头文件得到编译代码时所需的一些信息,然后才能把程序需要的内容(比如这里要用到的 test函数)替换到源文件中,最后才能正确编译为可执行程序。

比如现在要做一个学生管理库 student.h,这个库中提供了学生结构体的定义,以及对学生信息相关操作:

c 复制代码
// 学生结构体定义
struct stu {
    int id;
    int age;
    char name[20];
} typedef Student;

// 打印学生信息
void print(Student* student);

// 修改年龄
void modifyAge(Student* student, int newAge);

// 修改学号
void modifyId(Student* student, int newId);

再定义源文件 student.c:

c 复制代码
#include <stdio.h>
#include "student.h"

int main() {
    Student student = {1, 18, "小明"};
    modifyAge(&student, 19);
    print(&student);
}

void print(Student* student) {
    printf("ID: %d, 姓名: %s, 年龄: %d岁\n", student->id, student->name, student->age);
}

void modifyAge(Student* student, int newAge) {
    student->age = newAge;
}

void modifyId(Student* student, int newId) {
    student->id = newId;
}
c 复制代码
ID: 1, 姓名: 小明, 年龄: 19岁

通过使用#include就可以将项目拆分成多个模块去进行编写了。


环境:

  • GCC 11.4.0
  • VSCode 1.93.1
相关推荐
想做小南娘,发现自己是女生喵20 分钟前
QT项目实战第一周(嵌入式)
开发语言·qt
学逆向的27 分钟前
C 可变量参数
c语言·开发语言·网络安全
andyweike27 分钟前
kotlin dsl library工程怎么配置
android·开发语言·kotlin
huaweichenai34 分钟前
php搭建mcp服务
开发语言·php·ai编程
估值探索者1 小时前
【Python量化技术指标实战 02】MACD金叉也分强弱?手工算一次 DIF/DEA 就懂了
java·开发语言·python·股票数据·股票数据api接口
讳疾忌医丶1 小时前
编译器眼中的 C++ 循环:从指针别名、IEEE 754 结合律到 SIMD 语义证明
开发语言·c++
小莞尔1 小时前
【51单片机】【protues仿真】基于51单片机六路抢答器系统
c语言·单片机·嵌入式硬件·物联网·51单片机
重生六道1 小时前
B站视频时长统计:一段JS脚本搞定分P/合集总时长(附倍速计算)
开发语言·javascript·音视频
XiYang-DING1 小时前
P5528.带过期时间的 LRU 缓存
java·开发语言·缓存
小徐不徐说1 小时前
C++ 机器视觉入门:从零搭建 AOI 开发环境(OpenCV + CMake)
开发语言·c++·opencv