1.了解extern
1.extern是C语言的一个关键字,可以用来修饰函数与变量
2.当extern修饰一个变量或函数时时,就是在声明这个变量(函数),告诉编译器在外部文件中已经这个变量(函数),要通过编译。
2.extern的用法
1.在一个文件中引用其他文件的变量
当我们一个项目中有多个.cpp文件时,往往需要在其中一个文件中使用另一个文件中定义的变量,如果我们直接使用,编译器就会报错:
由于编译文件1的时候编译器不认识g_val,以此编译失败
这时我们就可以使用extern,如下:
//文件1.cpp代码
#include<stdio.h>
extern int g_val; //声明外部符号g_val
int main()
{
printf("%d", g_val);
}
//文件2.cpp代码
int g_val = 10;
这时,代码就可以成功运行起来,打印出g_val的值。
2.在一个文件中引用其他文件的函数
对于函数,也是同理,当需要使用外部文件定义的函数时,需要使用extern关键字进行声明:
//文件1.cpp代码
#include<stdio.h>
extern void show(); //声明外部符号show()
int main()
{
show();
}
//文件2.cpp代码
#include<stdio.h>
void show()
{
printf("hello world");
}
运行结果如下:
hello world
3.extern的注意事项
在使用extern时我们可能会写出这样的代码 :
//文件1.cpp代码
#include<stdio.h>
extern int g_val=10;
int main()
{
printf("%d", g_val);
}
//文件2.cpp代码
int g_val = 10;
上述代码是在引用外部变量g_val的时候同时对它进行赋值,当我们运行时,编译器就会报错,这个错误是在链接的时候发生的错误,为“找到一个或多个多重定义的符号” 。
产生错误的原因时什么呢 ?这就不得聊到定义与声明了。
1.什么定义:
定义是给变量或函数分配内存空间,在这同时可以为变量赋初值。
2.什么是声明:
声明是用来告诉编译器变量的名称和类型,使编译器知道存在着这个变量和类型,且不分配内存。
3.结论
由此我们可以得出以下两种结论:
1.定义会对变量分配内存空间,而声明不会
2.由于一个变量的存储空间是唯一的,因此定义不能重复定义,而声明可以重复声明。
由此可以得出,当我们使用extern修饰变量且对它进行赋值的时候,这条语句就不是在对变量进行声明了,而是定义,因为声明一个变量编译器是不会分配内存空间的,而对于一个不存在的内存空间进行赋值操作,显然是不合理的。
而当我们进行定义的时候,编译器在编译的时候并不会发现错误,但在多文件进行链接时,就会发现g_val这个全局变量同时在1.cpp和2.cpp进行定义,报出了重定义的错误。
4.extern与include
1. include
当我们有多个文件需要大量引用外部变量或函数的时候,如果使用extern,我们就需要在多个文件中大量使用extern,这样做效率显然会降低,代码也显得太过LOW。因此,我们通常将所有的全局变量和常用全局函数都写在一个.cpp文件中,然后用同名的.h文件放这些变量与函数的声明(即头文件),这样其他文件需要使用外部变量和函数时,就只需要包含其中的头文件即可,显得高效又简洁。如:
//文件1cpp代码
#include "2.h"
int main()
{
show();
printf("%d", g_val);
}
//文件2.cpp代码,用于定义与实现
#include "2.h"
int g_val = 10;
void show()
{
printf("hello world");
}
//文件2.h代码,用于声明
#pragma once //防止重复包含
#include<stdio.h>
extern int g_val;
void show();
这样,当我们需要使用2.cpp中的变量和函数时,就不需要再使用extern声明了
2.extern的好处
想必会有读者有疑问,include那么方便,那我们的extern关键字是不是没有用了?实则不然。原因如下:
1.当头文件中有大量的变量与函数时,如果我们只需要其中的少量变量或函数时,我们使用include包含,显然会引入大量不需要的无关函数与无关变量,这样无疑会减慢程序预处理的过程,此时使用extern就可以有效缩短时间。
2.在大工程中,一个头文件中经常会包含其他的头文件,这样层层嵌套下来,如果没有进行处理,往往会出现一个.c文件重复包含相同头文件的情况,而使用extern就不会出现这种情况。(当然,如果头文件进行适当的处理如“条件编译”,也能有效地避免重复包含的现象,这里先暂时不做详细讨论)
制作不易,能否点个赞再走呢qwq