extern

基本理解

extern放在变量或者函数之前,表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。

参考博客 https://www.cnblogs.com/WindSun/p/11434436.html

extern有两个作用

1.当它与"C"一起连用时,如: extern "C" void fun(int a, int b);告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非,可能是fun@aBc_int_int#%$也可能是别的(不同编译器不同),因为C++支持函数的重载。(详细转到另一篇博客:https://www.cnblogs.com/WindSun/p/11334182.html)

2.在头文件中: extern int g_Int; 它的作用就是声明全局变量或函数的作用范围的关键字,其声明的函数和变量可以在本模块或其他模块中使用,记住它是一个声明不是定义。也就是说B模块如果引用A模块中定义的全局变量或函数时,它只要包含A模块的头文件即可,在编译阶段,模块B虽然找不到该函数或变量,但它不会报错,它会在连接时从模块A生成的目标代码中找到此函数。

extern用在变量声明中常常有这样一个作用,在.c文件中声明了一个全局的变量,这个全局的变量如果要被引用,就放在.h中并用extern来声明。

注意

(1)extern数组变量

在一个源文件里定义了一个数组:char a[6],在另外一个文件里用下列语句进行了声明:extern char *a是不可以的,便宜可以通过,但运行时出现错误。

原因:指向类型T的指针并不等价于类型T的数组。extern char *a声明的是一个指针变量而不是字符数组,因此与实际的定义不同,从而造成运行时非法访问。应该将声明改为extern char a[ ]。

(2)extern全局变量

如果在一个test1.h头文件中将全局变量的声明和定义放在一起,

extern char g_str[] = "123456"; // 这个时候相当于没有extern

在两个.cpp文件中都有包含这个.h头文件,这时候再编译连接test1.cpp和test2.cpp两个模块时,会报连接错误,这是因为你把全局变量的定义放在了头文件之后,test1.cpp这个模块包含了test1.h所以定义了一次g_str,而test2.cpp也包含了test1.h所以再一次定义了g_str,这个时候连接器在连接test1和test2时发现两个g_str。如果你非要把g_str的定义放在test1.h中的话,那么就把test2.cpp的代码中#include "test1.h"去掉 换成在变量定义前面加上extern:extern char g_str[];这个时候编译器就知道g_str是引自于外部的一个编译模块了,不会在本模块中再重复定义一个出来,但是这样做非常糟糕,因为你由于无法在test2.cpp中使用#include "test1.h",那么test1.h中声明的其他函数你也无法使用了,除非也用都用extern修饰,这样的话你光声明的函数就要一大串,所以 请记住:只在头文件中做声明,真理总是这么简单。

(3)extern和static

static的全局变量作用域只在本文件中,所以extern和static不能同时修饰一个变量;
一般定义static全局变量时,都把它放在原文件中而不是头文件,这样就不会给其他模块造成不必要的信息污染。

(4)extern和const

C++中const修饰的全局常量据有跟static相同的特性,即它们只能作用于本编译模块中,但是const可以与extern连用来声明该常量可以作用于其他编译模块中, 如extern const char g_str[]; 然后在原文件中别忘了定义: const char g_str[] = "123456";

  1. const int p; // p is a int const. p是一个int型常量 这个很简单

  2. const int *p; //p is a point to int const. p是一个指针,指向int型常量。即p是一个指向int型常量的指针。

  3. int const *p; //与2相同 const int 和 int const 是一样的意思。《C++ primer》中采用第一种写法。

  4. int * const p; // p is a const point to int. p是一个指向int的const指针

extern于函数

  • extern 关键字放在函数声明之前:

test.h
extern int test();

如果这样函数的声明中带有关键字extern,仅仅是暗示这个函数可能在别的源文件里定义。
这样一来,就是在程序中取代include “*.h”来声明函数,在一些复杂的项目中,比较习惯在所有的函数声明前添加extern修饰,以防止遗漏包含头文件而导致的编译错误。

  • extern 关键字放在函数定义之前:

test.c
extern int test()
{
return true;
}

如果在函数定义的地方带有关键字extern,表示该函数会提供给外部文件使用,其实有些编译器是默认每个函数都是extern类型的,反之是static类型

posted @ 2020-02-17 16:32  friedCoder  阅读(526)  评论(0)    收藏  举报