gcc学习笔记1
本文最后更新于 2024年2月5日 下午
此文章是 gcc 学习笔记,学习视频
1 多文件编译
目录结构如下:

main.c(主程序):
1 | |
hello.h(函数的声明):
1 | |
hello.c(函数的实现):
1 | |
使用 gcc -Wall main.c hello.c -o hehe 命令进行多文件编译:

1.1 hello.h
在文件目录中有 hello.c、hello.h 和 main.c,但是在使用 gcc 编译时没有包含 hello.h
在 main.c 中的第二行 include 了 hello.h,gcc -Wall main.c hello.c -o hehe 在执行这条命令时,gcc 读取到 main.c 源文件中的第二行,就会去找 hello.h 文件自动包含进来,所以不用包含头文件。
1.1.1 " " 和 < >
在 main.c 中使用了 include <stdio.h> 和 include "hello.h",这两种不同的包含符号有什么区别?
" " 表示编译器首先会到当前路径(被编译的源文件所在的路径)下搜索这个头文件,找不到再去系统头文件目录。
而 < > 是直接去系统头文件目录下搜索头文件。
头文件目录(对于 Linux 系统)
/usr/include:系统上的标准头文件目录
/usr/local/include: 本地安装的软件包可能会将头文件放置在这个目录中
1.2 另外
在上述源文件中,hello.c 中的 include "hello.h" 可以删除,使用 gcc -Wall main.c hello.c -o hehe 编译时没有任何问题,为什么?
当 main.c 中包含了 hello.h 头文件时,这个头文件中的声明 void hello(const char* str); 告诉编译器有一个名为 hello 的函数,但是并没有提供该函数的具体实现。具体的实现在 hello.c 文件中。
编译器在编译 main.c 时,会查看 #include "hello.h",这会将 hello.h 文件的内容插入到 main.c 中。然后编译器会在 main.c 中找到函数声明 void hello(const char* str);。由于这只是一个声明,编译器并不知道函数的具体实现。
当你最后执行链接阶段(使用 gcc main.c hello.c -o hello)时,编译器会查找 hello 函数的实现。 这时,编译器看到了 main.c 中的调用 hello("呵呵,ojbk");,然后会在整个工程中搜索包含了 hello 函数实现的文件。由于你同时编译了 hello.c,所以编译器找到了 hello 函数的实现。 —— 正是因为同时将 main.c 和 hello.c 放在一起编译(gcc main.c hello.c -o hello)所以才不报错。
最终,链接器将 main.o 和 hello.o 这两个目标文件合并,生成了可执行文件 hello。