头文件、源文件 及extern的使用

头文件与源文件的作用

1. 编译器的工作过程

简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程:

1.预处理阶段
2.词法与语法分析阶段
3.编译阶段,首先编译成纯汇编语句,再将之汇编成跟CPU相关的二进制码,生成各个目标文件 (.obj文件)
4.连接阶段将各个目标文件中的各段代码进行绝对地址定位,生成跟特定平台相关的可执行文件,当然,最后还可以用objcopy生成纯二进制码,也就是去掉了文件格式信息。(生成.exe文件)

编译器在编译时是以C文件为单位进行的,也就是说如果你的项目中一个C文件都没有,那么你的项目将无法编译,连接器是以目标文件为单位,它将一个或多个目标文件进行函数与变量的重定位,生成最终的可执行文件,在PC上的程序开发,一般都有一个main函数,这是各个编译器的约定,当然,你如果自己写连接器脚本的话,可以不用main函数作为程序入口!!!!
(main .c文件 目标文件 可执行文件 )

2. 头文件与源文件的解析

1 . (.h)叫做头文件,它是不能被编译的。
    “#include”叫做编译预处理指令,可以简单理解成,在1.cpp中的#include"1.h"指令把1.h中的代码在编译前添加到了1.cpp的头部。每个.cpp文件会被编译,生成一个.obj文件,然后所有的.obj文件链接起来你的可执行程序就算生成了。
    发现了没有,你要在.h文件中严格区分声明语句和定义语句。好的习惯是,头文件中应只处理常量、变量、函数以及类等等等等的声明,变量的定义和函数的实现等等等等都应该在源文件.cpp中进行。
    至于.h和.cpp具有同样的主文件名的情况呢,对编译器来讲是没有什么意义的,编译器不会去匹配二者的主文件名,相反它很傻,只认#include等语句。但是这样写是一种约定俗成的编程风格,一个类的名字作为其头文件和源文件的主文件名比如Class1.h和Class1.cpp,这个类的声明在Class1.h中,实现在Class1.cpp中,我们人类看起来比较整齐,读起来方便,也很有利于模块化和源代码的重用。
    为什么这个风格会约定俗成?有一句著名的话,叫“程序是为程序员写的”。
2.h文件和cpp文件也就是说,
    在h文件中声明Declare,而在cpp文件中定义Define。 
    “声明”向计算机介绍名字,它说,“这个名字是什么意思”。而“定义”为这个名字分配存储空间。无论涉及到变量时还是函数时含义都一样。无论在哪种情况下,编译器都在“定义”处分配存储空间。
    对于变量,编译器确定这个变量占多少存储单元,并在内存中产生存放它们的空间。
    对于函数,编译器产生代码,并为之分配存储空间。函数的存储空间中有一个由使用不带参数表或带地址操作符的函数名产生的指针。
    定义也可以是声明。如果该编译器还没有看到过名字A,程序员定义int A,则编译器马上为这个名字分配存储地址。声明常常使用于extern关键字。如果我们只是声明变量而不是定义它,则要求使用extern。对于函数声明, extern是可选的,不带函数体的函数名连同参数表或返回值,自动地作为一个声明。

extern 关键字的使用

1. 主函数源文件中不包含头文件

test1.cpp 文件
int test = 10000;

void  test_fun(int& temp)
{
    temp += 1111;
}
主函数 yuan.cpp 文件
#include<iostream>
using namespace std;

extern int test;
extern void  test_fun(int& temp);

int main()
{
    cout << test << endl;
    test_fun(test);
    cout << test << endl;
    return 0;
}

总结:编写单独的 .cpp 文件来实现 函数 或者 变量 ,在主函数使用前需要声明变量为外部变量。不然编译可以通过,但是在目标文件链接的时候就会出错。

2. 主函数源文件中包含头文件

test.h 文件
#pragma once
#include<iostream>

using namespace std;

extern int intext; //外部变量
void test_function();
extern void function();//外部函数
test.cpp 文件
#include"test.h"

int intext = 10;

void test_function()
{
    cout << "test" << endl;
}
function.cpp 文件 (这个实现外部的函数)
#include<iostream>

void function()
{
    std::cout << "extern-function" << std::endl;
}
yuan.cpp 文件 (主函数)
#include"test.h"

int main()
{
    cout << intext << endl;
    test_function();
    function();
    return 0;
}

总结:可以通过建立一个.h文件来说明一些外部的变量和函数。这样通过引用头文件就可以实现真确的编译及链接。
参考:
https://www.cnblogs.com/with-a-orchid/p/4262951.html
https://www.cnblogs.com/fenghuan/p/4794514.html

猜你喜欢

转载自blog.csdn.net/qq_21033779/article/details/80004184
今日推荐