前面总结了static关键字,下面先说说static和extern能同时使用吗? 答案是不能。
extern修饰全局变量和函数,被修饰的变量和函数可以在别的文件里使用。
static修饰的变量和函数作用范围仅限于定义它的文件内部。
static要求去除符号表名称,extern要求通过符号名称链接,他俩先天就矛盾,不能一起使用。
说起extern 这个关键字,相信大家都用的很多,一般都是在编译程序的时候,出现了全局变量找不到,不是定义在本文件中,然后就会在前面加上extern来解决这类编译错误。 相对其他关键字,extern的使用比较简单。在此做个简单总结:
1.了解extern
1.extern是C语言的一个关键字,可以用来修饰函数与变量
2.当extern修饰一个变量或函数时时,就是在声明这个变量(函数),告诉编译器在外部文件中已经这个变量(函数),要通过编译。
3.extern关键字是C语言中的一个存储类别修饰符,它用来声明一个变量或函数是在其他文件中定义的,
2.extern的用法
在C语言中变量和函数有数据类型和存储类型两个属性,因此变量定义的一般形式为:存储类型 数据类型 变量名表;
C语言提供了一下几种不同的存储类型:
(1) 自动变量(auto)--------局部变量默认一般就是这个类型,
(2) 静态变量(static)-------前面学习过
(3) 外部变量(extern)-------这次学习的
(4) 寄存器变量(register)-------很少显示看见
(上面的auto、static、extern、register都是C语言的关键字),这里只分析extern关键字的使用
外部变量(全局变量)extern----全局静态存储区
标准定义格式: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进行定义,报出了重定义的错误。
extern关键字的作用有以下几点:
-
- 可以避免变量或函数的重复定义,提高代码的可维护性和可读性。
-
- 可以实现跨文件的数据或功能的访问,提高代码的复用性和灵活性。
-
- 可以控制变量或函数的作用域和链接属性,提高代码的安全性和效率。
-
extern关键字可以让不同的文件之间共享变量或函数,实现模块化编程。extern关键字的作用有避免重复定义,实现跨文件访问,控制作用域和链接属性等。extern关键字的用法有声明全局变量,声明函数,声明常量,声明数组等。extern关键字的注意事项有不能用于定义,不能用于声明局部变量,不能用于声明静态变量,声明和定义要一致,声明可以多次,定义只能一次等。
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 //防止重复包含 //还有一种可以防止重复包含的方法:#define XXX
#include<stdio.h>
extern int g_val;
void show();
这样,当我们需要使用2.cpp中的变量和函数时,就不需要再使用extern声明了,包含2.h就可以了。
2.extern的好处
想必会有读者有疑问,include那么方便,那我们的extern关键字是不是没有用了?实则不然。原因如下:
1.当头文件中有大量的变量与函数时,如果我们只需要其中的少量变量或函数时,我们使用include包含,显然会引入大量不需要的无关函数与无关变量,这样无疑会减慢程序预处理的过程,此时使用extern就可以有效缩短时间。
2.在大工程中,一个头文件中经常会包含其他的头文件,这样层层嵌套下来,如果没有进行处理,往往会出现一个.c文件重复包含相同头文件的情况,而使用extern就不会出现这种情况。(当然,如果头文件进行适当的处理如“条件编译”,也能有效地避免重复包含的现象,这里先暂时不做详细讨论)
帖子:
原文链接:https://blog.csdn.net/m0_69909682/article/details/128218337
https://blog.csdn.net/u012730525/article/details/136230556
https://blog.csdn.net/apple_51801179/article/details/125758014