C语言 extern

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言 extern相关的知识,希望对你有一定的参考价值。

参考技术A

在C语言中,变量和函数都有数据类型和存储类型两个属性,因此变量定义的一般形式是 存储类型 数据类型 变量名

C语言种提供了以下四种不同的存储类型

那么我们所说的extern就是存储类型的一种。extern修饰的变量存储位置在全局静态存储区。
标准的定义格式: extern 类型名 变量名;

通俗来说,如果使用extern修饰了一个变量或者函数,那么这个函数或者变量就变成了全局变量,在除定义该变量or函数的文件外仍然有效。不过需要注意的是,使用extern进行修饰是对该变量or函数进行声明,并没有分配内存。

如果在a.c中需要引用b.c中的int i,那么可以在a.c中使用extern int i进行声明。并且,能够被其他模块以extern修饰符引用的变量通常是全局变量。并且extern int i可以被放在a.c中的任何位置,区别只是在a.c中作用域的问题。

从本质上来说,并没有什么区别。函数名字本质上是一个指向二进制块开头处的指针。如果a.c中需要引用b.c中的函数,如b.c中原型是int fun(int mu),那么在a.c中声明extern int fun(int mu)那么就可以在a.c中用fun做事。

但是对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。

那么使用extern和包含头文件来引用函数有什么区别如下:
① 使用extern的引用比包含头文件要简介的多。extern使用直截了当,引用哪个函数直接extern进行声明即可。这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。
② include本质上是把include进来的这个文件原封不动的搬到当前文件中

a.c

b.c

转载理解C语言中的关键字extern

原文:理解C语言中的关键字extern

 

最近写了一段C程序,编译时出现变量重复定义的错误,自己查看没发现错误。使用Google发现,自己对extern理解不透彻,我搜到了这篇文章,写得不错。我拙劣的翻译了一下。(原文:http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/)

  我确定这篇文章对c语言的初学者会有很大的帮助,因为这将使他们更好更熟练的使用c语言。所以就让我先来说说extern关键字在变量和函数上的应用。最基本的extern关键字扩展了变量和函数的可见度。这可能就是它为什么命名为extern的原因。

几乎所有人都知道声明和定义变量(函数)的意义,但是为了这篇文章的完整性,我想弄清楚它们。声明一个变量(函数)只是表明这个变量(函数)存在于程序的某个地方,并没有为它们分配内存。但是,声明变量(函数)具有重要作用,那就是说明变量(函数)的类型。因此,当一个变量声明,程序知道变量的类型,在函数声明的情况下,程序知道函数的参数和返回类型。这就是所谓的声明。来到定义,当我们定义一个变量(函数),除了声明的作用,它也为该变量(函数)分配内存。因此,我们可以认为声明是定义的子集。从上面的说明,显而易见,变量(函数)可以声明多次,只能定义一次。

现在回到我们的主要目标:理解C语言中的关键字extern。我已经解释过声明定义的作用了,因为我们必须借助它们来理解关键字extern。我们先来了解一种简单的情况,extern对函数的作用。默认情况下,声明和定义一个函数,都有一个extern的前缀,这意味着在声明和定义函数时,前面不写extern,它也是默认存在的。例如下面的代码。

1
int foo(int arg1, char arg2);

声明的函数前面没有extern,但编译器会在前面加上关键字extern,如下

1
extern int foo(int arg1, char arg2);

定义函数的情况和上面一样(函数的定义是指带有函数体)。因此,每当我们定义一个函数的时候,前面总会有默认的关键字extern。由于声明可以多次重复,定义只能完成一次,我们可以看到一个函数的声明可以在多个C/H文件或单个的C/H文件中重复多次。但是该函数实际只定义了一次(仅在一个文件中)。这样的函数在整个程序中都是可见的,任何文件任何地方都可以调用。(通过函数的声明,编译器在编译时就知道函数定义在哪里)。

第二种情况,extern对变量的作用。如何声明一个变量而不定义它?这是一个理解extern对变量作用的重要问题,答案如下:

1
extern int var;

在上面,一个整型变量var被声明(没有定义,没有分配内存)。并且,根据需要,我们可以声明多次。

现在,如何定义一个变量?答案如下:

1
int var;

在这里,声明及定义了一个整型变量var(声明是定义的子集,定义一个变量就包含了声明),这里还为变量var分配了内存。现在,让我们感到惊讶的是,当我们定义或声明一个函数时,前面会有默认的extern,但对于变量的情况就不一样了。如果变量也和函数一样,那么它们永远不会分配内存,它们仅仅被声明。因此,当我们想要声明而不定义一个变量就需要加上关键字extern。此外extern将变量的能见度延伸到了整个程序,我们知道变量声明和定义的地方,可以在整个程序的任何地方使用它们。下面借助几个例子来理解extern

1
2
3
4
5
6
int var;
int main(void)
{
var = 10;
return 0;
}

分析:程序编译成功,var是一个全局变量(隐势声明)

1
2
3
4
5
extern int var;
int main(void)
{
return 0;
}

分析:程序编译成功,这里var只被声明,其他地方没有使用var,所以没问题。

1
2
3
4
5
6
extern int var;
int main(void)
{
var = 10;
return 0;
}

分析:程序编译错误,由于声明了变量var,而没有在其他地方定义,从本质上讲,没有为var分配内存,程序又要给它赋值。

1
2
3
4
5
6
7
#include "somefile.h"
extern int var;
int main(void)
{
var = 10;
return 0;
}

分析:如果文件somefile.h文件中有定义变量var, 程序将会编译成功。

1
2
3
4
5
6
extern int var = 0;
int main(void)
{
var = 10;
return 0;
}

分析:猜猜上面的代码能否编译成功?在这里按照C的标准是可以编译通过的。声明一个变量并给它初始化一个值,则该变量的内存将被分配,即该变量被定义。(有的编译器会报告一个警告:warning: ‘extern‘ variable has an initializer)

所以,我们可以得出结论:

  1. 声明可以多次,定义只能一次。

  2. 关键字extern用于扩展变量和函数的可见性。

  3. 由于函数默认存在extern,不需要再定义和声明的时候使用extern

  4. 当变量使用extern时,它只是声明没有定义。

  5. 当变量用extern声明并且有初始化时,和变量的定义一样。

以上是关于C语言 extern的主要内容,如果未能解决你的问题,请参考以下文章

将 C++ 中的“extern C”与 ctypes 的向量一起使用

更好地理解外部“C”函数

“C语言是中间语言”,中间语言是啥意思?

C语言和ARDUINO语言一样吗

C语言和其他高级语言有啥异同?

C语言诞生之前,都有哪些重要的编程语言?