C语言 20-static和extern关键字2-对变量的作用

本文目录

  • 一、在Java中,全局变量的定义没有严格的位置规定
  • 二、在C语言中,全局变量定义的位置是有限制的
  • 三、重复定义同一个变量
  • 四、不同源文件中的同名变量
  • 五、static关键字
  • 六、static和extern的总结

  说明:这个C语言专题,是学习iOS开发的前奏。也为了让有面向对象语言开发经验的程序员,能够快速上手C语言。如果你还没有编程经验,或者对C语言、iOS开发不感兴趣,请忽略。

  上一讲介绍了static和extern对函数的作用,static用来定义一个内部函数,不允许其他文件访问;extern用来定义和声明一个外部函数,允许其他文件访问。static和extern对变量也有作用,不过跟函数有点差别。

  C语言和Java都有全局变量的概念,但是它们的用法还是有些差别的。

一、在Java中,全局变量的定义没有严格的位置规定

全局变量可以定义在类的最前面,也可以定义在类的最尾端,也就说一个方法可以访问在它之后定义的变量。

可以看到,第4行定义的test方法可以访问第8行定义的变量a,这是完全没有问题的。

二、在C语言中,全局变量定义的位置是有限制的

默认情况下,一个函数不可以访问在它后面定义的全局变量

在第4行定义的main函数中尝试访问第9行定义的变量a,编译器直接报错了。

解决这个错误的话,有2种办法:

第1种办法:将变量a定义在main函数的前面

这样做编译器就不会找你麻烦了。

第2种办法:在main函数前面对变量a进行提前声明

也就是让main函数知道变量a的存在就行了,至于变量a定义在哪个位置,main函数不用管。

* 完整的变量声明需要用extern关键字

第3行是对变量a进行声明,第10行是定义变量a,再次强调,声明和定义是两码事。在第6行操作的就是第10行定义的变量a。

注意:你不能省略第10行的定义,只留下第3行的声明,因为extern是用来声明一个已经定义过的变量。

三、重复定义同一个变量

* 其实,你也可以直接在main函数前面再定义一次a

看到这一幕,你可能很惊讶,但编译器是不会报错的。在这种情况下,第3行和第10行的变量a代表着同一个变量。

* 以此类推,如果我们写了无数遍全局变量int a;,它们代表的都是同一个变量。

第3到第6行、第13到第17行的变量a都代表着同一个变量。

* 还要注意的一点是,我们也可以将全局变量a声明为局部变量后再使用!!!

注意:第2、第5、第6、第10行都代表着同一个变量。其实,从第6行a的颜色(浅蓝色)都可以看出,这个a依然是个全局变量。

(这是Xcode的特性,如果在函数内部访问了全局变量,全局变量就会显示浅蓝色,如果函数内部访问的是局部变量,局部变量就显示普通的黑色。当然,不同的开发工具有不同的显示方案)

* 但是,如果你将第5行的extern去掉,那情况就完全不一样了,相信有编程经验的你都懂得这是什么情况了

第2、第10行代表着同一个全局变量,而第5、第6行则是一个局部变量,跟外面的那个全局变量没有半毛钱的关系。其实从第5、6行a的颜色(黑色)都可以看出是个局部变量。

四、不同源文件中的同名变量

  前面讲到,你在一个源文件中无论写多少遍全局变量int a;,它们代表的都是同一个变量。还有一个事实,假如在另一个源文件中也有全局变量int a;,那么这两个源文件的所有全局变量int a;都代表着同一个变量。

   

注意:main.c和test.c中的全局变量a都代表着同一个变量。

我们可以证明一下:

首先,在test.c中定义一个函数来查看a的值

然后在main.c的第9行修改a的值为10,然后调用test.c的test函数看看test.c中a的值

控制台的输出

已经证明了一切。

* 当然,extern关键字还是适用的,比如:

或者是:

上面的两种情况下,test.c和main.c中使用的全局变量a都还是代表着同一个变量

注意了,不可以两个文件的所有全部变量a都用extern,下面的做法是错误的:

因为extern是用来声明一个已经定义过的变量,这两个文件都是在声明变量,没有人定义变量,在链接的时候肯定报错:

大致错误意思是:标示符a未定义

五、static关键字

但很多时候,我们并不想让源文件中的全局变量跟其他源文件共享,相当于私有的全局变量,那么你就得用static关键字来定义变量。

这样写完,test.c和main.c的变量a分别代表着不同的变量,它们是没有联系的、互不干扰的。也就是说,main.c无法访问test.c中的变量a,因此在main.c中将a修改为10后,test.c中的a依然为0。输出结果:

其实static还可以用来修饰局部变量,这个在《变量类型》中说过,不再阐述了。

* 因为main.c已经没有权限访问test.c中的变量a了,所以下面的写法是错误的:

extern是用来声明已经定义过而且能够访问的变量,虽然test.c中有定义过变量a,但是test.c中变量a的作用域是只限于test.c文件,main.c没有访问权限,所以main.c中的extern是废的。

链接的时候报错:标示符a未定义

除非main.c自己定义一个变量a,这样子extern才是有效的,不过这时候main.c和test.c中的变量a是分别代表着不同变量

六、static和extern的总结

1.extern可以用来声明一个全局变量,但是不能用来定义变量。

2.默认情况下,一个全局变量是可以供多个源文件共享的,也就说,多个源文件中同名的全局变量都代表着同一个变量。

3.如果在定义全局变量的时候加上static关键字,此时static的作用在于限制该全局变量的作用域,只能在定义该全局变量的文件中才能使用,跟其他源文件中的同名变量互不干扰。

时间: 2024-08-01 00:05:43

C语言 20-static和extern关键字2-对变量的作用的相关文章

黑 马 程 序 员_视频学习总结<C语言>----07 static和extern关键字、typedef

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 一.外部函数 外部函数:如果在当前文件中定义的函数允许其他文件访问.调用,就称为外部函数.C语言规定,不允许有同名的外部函数 二.内部函数 内部函数:如果在当前文件中定义的函数不允许其他文件访问.调用,只能在内部使用,就称为内部函数.C语言规定不同的源文件可以有同名的内部函数,并且互不干扰. 三.static.extern与函数的总结 1.在定

【黑马程序员】————static和extern关键字2-对变量的作用

C语言和Java都有全局变量的概念,但是它们的用法还是有些差别的. 一.在Java中,全局变量的定义没有严格的位置规定 全局变量可以定义在类的最前面,也可以定义在类的最尾端,也就说一个方法可以访问在它之后定义的变量. 可以看到,第4行定义的test方法可以访问第8行定义的变量a,这是完全没有问题的. 二.在C语言中,全局变量定义的位置是有限制的 默认情况下,一个函数不可以访问在它后面定义的全局变量 在第4行定义的main函数中尝试访问第9行定义的变量a,编译器直接报错了. 解决这个错误的话,有2

【黑马程序员】————static和extern关键字1-对函数的作用

一.extern与函数 如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用c.obj中定义的一个函数.将这些相关联的目标文件链接在一起后才能生成可执行文件. 先来理解2个概念: 外部函数:如果在当前文件中定义的函数允许其他文件访问.调用,就称为外部函数.C语言规定,不允许有同名的外部函数. 内部函数:如果在当前文件中定义的函数不允许其他文件访问.调用,只能在内部使用,就称为内部函

转载 浅谈C/C++中的static和extern关键字

浅谈C/C++中的static和extern关键字 2011-04-21 16:57 海子 博客园 字号:T | T static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明.本文主要介绍C/C++中的static和extern关键字. AD: static是C++中常用的修饰符,它被用来控制变量的存贮方

static 和extern关键字

static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明.本文主要介绍C/C++中的static和extern关键字. static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern, "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方

static 和 final 关键字 对实例变量赋初始值的影响

static 和 final 关键字 对实例变量赋初始值的影响 最近一直在看<深入理解Java虚拟机>,在看完了对象内存分配.Class文件格式之后,想深扒一下实例变量是如何被赋上初始值的这个问题的细节. 在2.3.1小节中讲对象创建的时候,讲到内存分配有两种方式:一种是指针碰撞:另一种是空闲列表. 而选择哪种分配方式是由JAVA堆是否规整决定,而JAVA堆是否规整则由虚拟机所采用的垃圾收集器是否带压缩整理功能决定. 我们不管内存分配采用何种方式,当内存分配完成后,虚拟机将分配到的内存空间都初

18-C语言static和extern关键字1-对函数的作用

一.extern与函数 在第三讲和第四讲中,我提到过一句话:如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用c.obj中定义的一个函数.将这些相关联的目标文件链接在一起后才能生成可执行文件. 先来理解2个概念: 外部函数:如果在当前文件中定义的函数允许其他文件访问.调用,就称为外部函数.C语言规定,不允许有同名的外部函数. 内部函数:如果在当前文件中定义的函数不允许其他文件访问

C语言学习入门 (七) 变量与函数,static和extern关键字

局部变量 1> 定义:在函数内部定义的变量,称为局部变量.形式参数也属于局部变量. 2> 作用域:局部变量只在定义它的函数内部有效,即局部变量只有在定义它的函数内部使用,其它函数不能使用它. 全局变量 1> 定义:在所有函数外部定义的变量,称为全局变量. 2> 作用域:全局变量的作用范围是从定义变量的位置开始到源程序结束,即全局变量可以被在其定义位置之后的其它函数所共享. 变量的存储类型 C语言根据变量的存储类型(变量存储的位置:1. 运行时堆栈 2.普通内存 3.寄存器)的不同,

19-C语言static和extern关键字2-对变量的作用

一.在Java中,全局变量的定义没有严格的位置规定 全局变量可以定义在类的最前面,也可以定义在类的最尾端,也就说一个方法可以访问在它之后定义的变量. 可以看到,第4行定义的test方法可以访问第8行定义的变量a,这是完全没有问题的. 二.在C语言中,全局变量定义的位置是有限制的 默认情况下,一个函数不可以访问在它后面定义的全局变量 在第4行定义的main函数中尝试访问第9行定义的变量a,编译器直接报错了. 解决这个错误的话,有2种办法: 第1种办法:将变量a定义在main函数的前面 这样做编译器

15-static和extern关键字1-对函数的作用

一.extern与函数 如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用c.obj中定义的一个函数.将这些相关联的目标文件链接在一起后才能生成可执行文件. 先来理解2个概念: 外部函数:如果在当前文件中定义的函数允许其他文件访问.调用,就称为外部函数.C语言规定,不允许有同名的外部函数. 内部函数:如果在当前文件中定义的函数不允许其他文件访问.调用,只能在内部使用,就称为内部函