【C语言】模块划分、编译器工作原理 | 您所在的位置:网站首页 › 函数模块化C语言 › 【C语言】模块划分、编译器工作原理 |
模块划分
在实际应用中,一个较大的 C 程序并不会把所有代码都放入 main 主函数中,而是进行模块化设计,每个程序模块作为一个源程序文件,再由若干源程序文件组成一个 C 程序。这样处理便于分别编写、分别编译、进而提高调试效率。 #include void func1(){ //函数声明并定义 printf("hello\n"); } int func2(int i); //函数声明 int main() { func1(); //函数调用 int i = func2(3); //函数调用 printf("%d\n",i); return 0; } int func2(int i) { //函数定义 printf("%d\n",i); return i+2; }现在将上述代码拆分为两个源程序文件 func.c 和 main.c,同时添加一个头文件 func.h。 一般情况下在 .h 文件中进行变量、函数和宏的声明,在 .c 文件中进行变量和函数的具体实现。 func.h 文件如下: #include int func2(int i); void func1();func.c 文件如下: #include "func.h" void func1(){ printf("hello\n"); } int func2(int i) { printf("%d\n",i); return i+2; }main.c 文件如下: #include "func.h" int main() { func1(); //函数调用 int i = func2(3); //函数调用 printf("%d\n",i); return 0; } Tips: #include 是从 C 语言标准库中查找头文件; #include "" 是从源代码所在目录中查找头文件,一般自己编写的头文件用引号。ps:为什么经常见 xx.c 中 include 对应的 xx.h?因为如果 .c 中的函数也需要调用同个 .c 中的其他函数,那么这个 .c 往往会 include 同名的 .h,这样就不需要为声明和调用顺序而发愁。这已经成为了一种代码规范。 编译器工作原理 预处理阶段:实际上是处理 define 和 include 等宏命令,进行宏替换。例如 #include "xx.h" 就是把这一行删掉,把 xx.h 中的内容原封不动地插入在当前行位置。 编译阶段:以 .c 文件为基本单位进行。这一阶段为所有 .c 文件中的变量、函数分配空间,并将各个全局变量、函数进行符号描述,编译、汇编成二进制码从而生成 .o 目标文件。(这一阶段并不关心变量的具体定义和函数的具体实现,只要存在变量和函数的相关声明即可通过编译) 链接阶段:以 .o 文件为基本单位进行,主要的工作是重定位各个目标文件的函数、变量,生成可执行文件。这个过程主要是找到变量和函数的具体定义和实现。 注意点 注意点一:C是否支持函数重载?函数重载是函数的一种特殊情况: C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。 C语言是不支持函数重载的。因为编译的时候,两个重载函数,函数名相同,一个名字对应多个地址,在 func.o 中的符号表中表示歧义,链接时也存在冲突,所以不支持。 如果有需求,可以用static关键字修饰其中一个函数,把该函数限制在其所在文件里。 拓展:C++引入了函数名修饰规则,用修饰过的函数名去符号表中匹配或者查找,保证不冲突。 注意点二:舍弃 .h 文件?如果舍弃 .h 文件,在 .c 文件中包含变量、函数的声明以及实现,这时候其他 .c 文件用 #include 去包含这个 .c 文件就会出现问题。 func.c 文件: #include void func1(); void func1(){ printf("hello\n"); }main.c 文件: #include "func.c" int main() { func1(); return 0; }
如此编译后生成的 main.o 文件中就不再包含 func1 函数的实现。但是如果 func.c 中的函数很多,以及调用这些函数的 .c 文件也很多,这样在每个 .c 文件中手动挨个添加这些函数的声明就十分繁琐。.h 文件就是为了声明函数和变量方便而诞生的,将所有的变量和函数声明都写在 .h 文件中,其他 .c 文件只需 #include 相应的 .h 文件即可。 注意点三:.h 文件中 #ifndef、#define和#endif.h 文件中 #ifndef、#define和#endif的作用是防止头文件在一个 .c 文件中被重复包含。 a.h 文件: struct Node{ int val1; int val2; };b.h 文件: #include "a.h"c.h 文件: #include "a.h"main.c 文件: #include "b.h" #include "c.h" int main() { return 0; }a.h 中的内容被两次复制到 main.c 中,产生 struct Node 重复定义错误。 修改 a.h 内容: #ifndef _A_H #define _A_H struct Node{ int val1; int val2; }; #endif那么 a.h 在 main.c 中只会被替换一次,避免了头文件的重复包含。 本文来自博客园,作者:hzyuan,转载请注明原文链接:https://www.cnblogs.com/hzyuan/p/17962331 |
CopyRight 2018-2019 实验室设备网 版权所有 |