C语言外部变量的使用以及erxtern的用法

网上有很多帖子问C语言中extern的用法,而且回答的详细程度各尽不同. 所以我就像写一篇博文来谈谈我对extern的看法,不一定十分恰当,只当大家共勉.

变量定义性声明和引用性声明



变量的声明有两种情况:
1、一种是需要建立存储空间的。
例如:int a 在声明的时候就已经建立了存储空间。
2、另一种是不需要建立存储空间的。
例如:extern int a 其中变量a是在别的文件中定义的。

前者是“定义性声明(defining declaration)”或者称为“定义(definition)”,而后者是“引用性声明(referncing declaration)”或者简成为“声明(Declaration)”,从广义的角度来讲声明中包含着定义,即定义是声明的一个特例,所以并非所有的声明都是定义

例如:int a; // 它既是声明,同时又是定义。
然而对于 extern int a;// 来讲它只是声明不是定义。
extern int a = 10;  // 定义一个变量,同时初始化为10,只是定义不再是声明

注意: 由于C语言中定义变量的默认存储类型是extern的
因此:
int a = 10;   等价于  extern int a = 10;  //  只是定义不是声明,但是extern int a = 10;作为定义在gcc下会有警告
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

一般的情况下我们常常这样叙述,把建立空间的声明称之为“定义”,而把不需要建立存储空间的声明称之为“声明”。很明显我们在这里指的声明是范围比较窄的,即狭义上的声明,也就是说非定义性质的声明

变量的声明和定义与extern



在具体到extern的用法之前,有两个概念必须要能分清楚:
声明(Declaration)定义(Definition)之间的区别.

声明一个变量只是宣布这个变量的属性,也就是说告诉编译器这个变量时什么类型(如int, long, string 等).
定义一个变量不仅是声明了变量的属性,同时也告诉编译器给变量分配相应的存储空间.

extern的用法详解



在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。

extern修饰变量的声明。



举例来说,如果文件main.c需要引用extern.c中变量int value,就可以在main.c中声明extern int value,然后就可以引用变量value。

这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说main.c要引用到value,不只是取决于在main.c中声明extern int value,还取决于变量value本身是能够被引用到的。这涉及到c语言的另外一个话题--变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全局变量。还有很重要的一点是,extern int value可以放在main.c中的任何地方,比如你可以在main.c中的函数fun定义的开头处声明extern int value,然后就可以引用到变量value了,只不过这样只能在函数fun作用域中引用value罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑。好像extern声明只能用于文件作用域似的。
总结起来可以这样说,声明只是告诉编译器声明的变量和函数是存在的,但并没有真正分配空间给它,所以当后面的代码用到前面声明的变量或函数时,编译器在编译的时候不会报错。链接的时候编译器会去寻找这些变量和函数的内存地址,如果只声明了但没定义,链接器当然找不到它们了,所以就会报错。而对它们进行定义了的话,编译器就会给它们分配空间,它们就有自己的地址了,这时就能链接了。定义是要分配空间的,且定义只能有一次。而声明不分配空间,可以声明多次。

extern修饰函数声明



从本质上来讲,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。如果文件main.c需要引用extern.c中的函数,比如在extern.c中原型是int fun(int num),那么就可以在main.c中声明extern int fun(int num),然后就能使用fun来做任何事情。就像变量的声明一样,extern int fun(int mu)可以放在main.c中任何地方,而不一定非要放在main.c的文件作用域的范围中。
对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。

使用extern和包含头文件来引用函数有什么区别呢?

extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。这大概是KISS原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。

extern修饰符可用于指示C或者C++函数的调用规范



比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同。

总结



关键字extern用来声明一个变量(或函数),并指出它具有外部链接(它的名字在其它文件里是可见的)。被extern修饰的变量,其生存期为程序运行的整个过程(它在程序开始运行时被分配内存,在程序运行结束时才被收回)。被extern声明的变量(或函数)将在同一文件的后续部分定义,或定义在其它的源文件中。

在C语言中,关键字extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。关键字extern用于变量的声明:

示例

extern.c

/**********************************************************
    > File Name: extern.c
    > Author: GatieMe
    > Mail: gatieme@163.com
    > Created Time: 2015年03月27日 星期五 16时11分50秒
 *********************************************************/

#include <stdio.h>
#include <stdlib.h>

extern int ex_num = 20; // 作为变量定义会有警告
int num = 30;
int value;
char str[81] = "abcdefg";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

main.c

/**********************************************************
    > File Name: main.c
    > Author: GatieMe
    > Mail: gatieme@163.com
    > Created Time: 2015年03月27日 星期五 16时12分14秒
 *********************************************************/

#include <stdio.h>
#include <stdlib.h>

extern int num;         //  声明一个外部变量,定义时使用int num = 30;

extern int ex_num;      //  声明一个外部变量,定义时2使用extern int ex_num = 20;
extern int value;       //  声明一个外部变量,定义时使用int value;

extern char str[81];

int a;                  //  既是声明也是定义
extern int b;           //  只是声明不是定义
int c = 10;             //  只是定义不是声明
extern int d = 20;      //  只是定义不是声明, 但是作为变量定义会有警告

int main(void)
{

    printf("num = %d\n", num);
    printf("ex_num = %d\n", ex_num);
    printf("value = %d\n", value);
    printf("str = %s\n", str);

    printf("a = %d\n", a);
//  printf("%d\n", b);  // ERROR, 链接错误,找不到变量定义
    printf("c = %d\n", c);
    printf("d = %d\n", d);

    return EXIT_SUCCESS;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

Makefile

#Makefile
main:extern.o main.o
    gcc $^ -o $@

extern.o:extern.c
    gcc  -c $^ -o $@ 

main.o:main.c
    gcc  -c $^ -o $@ 

clean:
    rm extern.o main.o
    rm main

转载:http://blog.csdn.net/gatieme/article/details/44678447

时间: 2024-11-01 17:00:16

C语言外部变量的使用以及erxtern的用法的相关文章

C程序中外部变量与函数关系解惑

C程序由一组对象组成,这些对象包括程序中所使用的变量和实现特定功能的函数.变量可以分为函数内部定义.使用的变量和函数外部定义的变量,通常情况下,把函数内部定义.使用的变量称为内部变量或局部变量,而将在函数外部定义的.供许多函数所使用的变量称为外部变量,一般情况下,也可以称为全局变量. 由于C语言不允许在一个函数中定义其他函数,因此函数本身是外部的.一般情况下,也可以说函数是全局函数. 在缺省情况下,外部变量与函数具有如下性质:所有通过名字对外部变量与函数的引用(即使这种引用来自独立编译的函数)都

iOS Block捕获外部变量和ARC自动拷贝block

Block内引用外部变量的问题 #define BLog(prefix,obj) {NSLog(@"位置和指针变量名:%@ ,指针内存地址:%p, 指针值:%p ,指向的对象:%@ ",prefix,&obj,obj,obj);} // 强引用 - (void)blockVariableStrongReferenceTest { NSLog(@"\n"); NSObject *obj = [[NSObject alloc] init]; BLog(@&quo

linux shell awk获得外部变量(变量传值)简介_linux shell

AWK 提供了极其强大的功能: 可以进行正则表达式的匹配 样式装入 流控制 数学运算符 进程控制语句 内置的变量和函数 可以把awk看作一门完全的程序设计语言,它处理文本的速度是快得惊人的.现在很多基于shell 日志分析工具都可以用它完成.设计简单,速度表现很好. 涉及到以上六个方面内容,我会在以后文章中加以介绍. 这次主要说下,怎么样把外部变量传入到awk执行语句中. 一.基础: awk [ -F re] [parameter...] ['pattern {action}' ] [-f pr

c语言-C语言中变量类型的范围会因为CPU的位数变化而不同吗?

问题描述 C语言中变量类型的范围会因为CPU的位数变化而不同吗? C语言中变量类型(short.int.long.char.float.double)的范围会因为CPU的位数变化而不同吗?这里的位数指的是什么?和操作系统的位数是同样的东西吗? 解决方案 会的. 在c语言中int型数据的长度就是CPU的位数.

system-C语言交换变量的问题?

问题描述 C语言交换变量的问题? 测试环境:vs2013 代码如下 # include<stdio.h> # include<stdlib.h> int main() { int a = 1; int b = 2; int t = 0; //法1 t = a; a = b; b = t; printf("a=%d b=%d t=%dn", a, b, t); //输出结果 a=2 b=1 t=1 a = 1; //重新给a b t赋为原来的值 b = 2; t

内部变量和外部变量就是局部变量和全局变量吗?

问题描述 内部变量和外部变量就是局部变量和全局变量吗? 局部变量和全局变量是从作用域分类的 外部变量就是前面加了extern,这个是从生存期定义的 这个两者应该不能混为一谈 为什么很多地方就默认为内部变量和外部变量就是局部变量和全局变量 这样子的话那么这句话怎么理解呢? 解决方案 首先把对应的外部和内部分别说成是全局和局部,这个内外表示的域(即{})的内外,而不是extern表示的文件的内外.不过确实很多的时候这样的表示由于没有统一的叫法,不同的作者有自己的叫法,常常让读书的人费解.你ppt截图

求解决-c语言数据变量赋值类型

问题描述 c语言数据变量赋值类型 假定有一个程序,它把一个long整型变量赋值给一个short整型变量.当你编译程序的时候会发生什么情况?当你运行程序时会发生什么情况?你认为其他编译器的结果是否也是如此? 解决方案 long整型变量赋值给一个short整型 会报错,类型转换出错,long转short大范围转小范围错误 解决方案二: C语言是一种简陋而充满陷阱的语言,它需要程序员格外小心,而不是依赖完备的运行时检查和编译检查. 其它编译器,如果是C编译器,大多如此.当然现代的C++编译器,比如VC

c语言-C语言中变量名称里面可以存在空格吗

问题描述 C语言中变量名称里面可以存在空格吗 解决方案 不可以.但是这里的空格不是变量之间的空格,而是变量和变量类型之间的空格. 好比 static int a; 解决方案二: 变量名 只能由 字母,数字,下划线组成 而且不能以数字开头哦~ 解决方案三: 不可以的,可以用下划线分割单词.图中的情况是类型和变量名直接,当然有空格了,那些类型其实就是用typedef或者宏定义的 解决方案四: 不可以!!!!!!!!!!!!! 解决方案五: 文件名可以用空格,变量名为什么不可以?因为编译器中空格就是分

语言相关-变量类型

语言相关 - 变量类型 所谓变量是指在为了快速读取而在内存中保存数据的一块空间. 您可以把它想象成是一个在内存里的邮箱, 我们可以往里面存信也可以取信.例如您可以创建 一个变量用来保存用户回复的数值或者某个数学表达式的 运算结果. 每个变量都有自己的名字(这跟邮箱是不是很像?)而且必须以英文 字符"$"开头,其中只能包含 字母, 数字 和下划线_字符.  下面是一些有效的变量名:     $var1     $my_variable   每个变量都储存为一个Variant.   变量的