C 头文件中函数声明定义
定义只能有一次,而声明的次数不限。任何标识符在使用前至少要有声明,将声明放在头文件中,就可以在需要使用到标识符时随时把头文件包含进来即可。如果把定义放进头文件中,那每包含一次头文件,标识符就定义了一次,这样在多文件的编译连接时很容易出问题的。 包含其实就相当于把被包含文件的内容加入到其中,和用被包含文件中的内容替换掉对应的包含语句没有区别。使用头文件的好处就是免除了重复劳动的麻烦。反正最终编译器都是把被包含文件的内容合并到一块才编译的。 所以这样,LZ觉得运行时的调用跟调用任何一个函数有区别吗。源文件不是连接的,源文件之间可以用包含,也就是可以用#include 。而连接是针对目标文件...全部
定义只能有一次,而声明的次数不限。任何标识符在使用前至少要有声明,将声明放在头文件中,就可以在需要使用到标识符时随时把头文件包含进来即可。如果把定义放进头文件中,那每包含一次头文件,标识符就定义了一次,这样在多文件的编译连接时很容易出问题的。
包含其实就相当于把被包含文件的内容加入到其中,和用被包含文件中的内容替换掉对应的包含语句没有区别。使用头文件的好处就是免除了重复劳动的麻烦。反正最终编译器都是把被包含文件的内容合并到一块才编译的。
所以这样,LZ觉得运行时的调用跟调用任何一个函数有区别吗。源文件不是连接的,源文件之间可以用包含,也就是可以用#include 。而连接是针对目标文件和库文件的。整个完整的Build编译过程实际上具体是分四步进行的,即预处理、编译至汇编代码、汇编编译、连接目标文件与库。
一般看不到或者不需要注意中间这些环节的。预处理阶段,负责头文件包含和宏替换等所有以“#”号开头的指令行的处理工作,找不到头文件的错误发生在此阶段。编译阶段,分编译到汇编代码和将汇编编译成机器代码,大多数编译器默认选择的是跳过产生汇编代码的阶段直接产生目标文件。
目标文件中包含的是编译后各个标识符的定义和函数的机器指令代码。源文件是分开编译的,每个。c源代码文件单独产生一个。obj目标文件。所有词法和语法性错误和警告在此阶段发生,因为此编译阶段完成意味着目标文件中的函数代码片段是可以交由CPU去执行的具体机器指令了。
连接是针对。obj目标文件和相关的。lib库文件,连接形成最终的。exe可执行文件。每个项目中生成一个。exe可执行文件。同一个项目中的多个源文件产生的目标文件参与同一个。exe可执行文件的生成。
C不生成。com可执行文件,那是汇编语言干的。C要求每个项目都要有而且只能有一个main函数的定义。由main函数引用到的所有名字,比如调用了什么函数,对哪个变量进行读写操作等涉及到的标识符,连接程序自动到项目的各个目标文件中去找这些名字的定义,然后到库文件中去找,目标文件中的函数还可能又引用到更多的标识符。
直到所有名字的定义都找到,将它们全部串接到一起,排好地址记录并打包就成了。exe可执行文件。如果头文件出问题,则连接时多半会发生“找不到XXX符号的定义”或者“XXX符号定义冲突”等错误。LZ暂时只需知道编译实际是分多个阶段进行的这句话就够了,等需要自己调试编译时才需要了解这些详情。
收起