一起talk C栗子吧(第一百二十六回:C语言实例--static关键字)



各位看官们,大家好,上一回中咱们说的内置宏的例子,这一回咱们说的例子是:static关键字。闲话休提,言归正转。让我们一起talk C栗子吧!

看官们,C语言提供了static关键字,它经常出现在变量或者函数的最前面,为什么要加上它呢?它主要有什么作用呢?今天我们一起来了解static关键字。

在介绍之前,我们先做一些铺垫。主要是介绍一下变量或者函数的生命周期和作用域。

变量和函数的生命周期

所谓的生命周期就是指变量或者函数在程序中可以被使用的时间,它是一段时间,可能是一分钟或者一小时等。生命周期通常从开始使用变量的时间算起,直到结束使用变量为止,在这个时间段内的时间就叫作变量的生命周期。这有点类似自然界的春夏秋冬,每年都是从春天开始,直到冬天结束。从春天到冬天的这个过程就是一个周期,只是我们习惯叫这个周期为一年。

C语言中的变量有全局变量和局部变量,全局变量的生命周期和程序的生命周期相同,也就是说全局变量贯穿于整个程序的运行过程。局部变量的生命周期没有这么长,它只在需要使用它的时候才开始出现,使用完成后,它完成了自己的使命,进而结束生命。最常见的是函数中的变量,这些变量都是局部变量,它们随着函数的运行而开始,函数运行结束后,它们也会消失。

接下来我们举一个实际的例子来说明变量的生命周期:

int globle_value = 1;

void func()
{
    int local_value = 3;

    printf("globle_value = %d \n",globle_value); //在该函数中可以使用全局变量
    printf("local_value = %d \n",local_value);   //在该函数中可以使用局部变量

}

int main()
{
    func();
    printf("globle_value = %d \n",globle_value); //在主函数中可以使用全局变量
    //printf("local_value = %d \n",local_value); //在主函数中不能使用局部变量

    return 0;
}

我们把上面的代码保存到一个文件中,并且编译该文件,然后运行编译后的程序,程序的运行结果如下:

globle_value = 1    //在func函数中可以使用全局变量
local_value = 3     //在func函数中可以使用全局变量
globle_value = 1    //在main函数中只能使用全局变量

从上面的例子中可以看到,全局变量在自定义的func函数和主函数中都可以被使用,因为它的生命周期和程序的生命周期相同。而局部变量只能在func函数中使用,不能在主函数中使用,如果去掉程序中的注释那么就会产生“变量未定义”的编译错误。原因在于局部变量随着func函数的结束而结束,因此在主函数中看不到局部变量。

变量和函数的作用域

变量的作用域表示变量的有效使用范围,变量在某个范围内可以被使用,出了这个范围外就不能被使用了。比如我们日常生活中的身份证,在国内可以随意使用,但是出国后就不能使用了,只能使用护照。这是因为身份证的作用域是国内,出国后就表示超出了身份证的作用域范围,这时就不能再使用身份证了。我们还使用上面的例子进行说明:

  • 全局变量globle_value的作用域是整个文件,因此它可以被同一个文件中的func函数和main函数访问。
  • 局部变量local_value的作用域是函数func内部。因此它只能在func函数内使用,在其它地方不能使用,因为已经超出了它的作用域。

有了这些铺垫后,我们介绍static关键字就容易多了,static关键字主要有两个功能:限定变量或者函数的生命周期和作用域。

对于变量来说,static不会影响它的生命周期,只是会把未初始化的变量初始化为0。不过它会缩小变量的作用域,这个对局部变量没有影响,主要是把全局变量的作用域缩小到一个文件中,比如我们在上面例子中的全局变量globle_value,它可以在其它文件中使用,如果把它使用static关键字限定后,它就只能在当前的文件中使用了。

下面是一个实际的例子,请大家参考:

static void func()
{
    int temp;
    static int static_local_value ;

    printf("temp = %d \n",temp); // default value is not known
    printf("static_local_value = %d \n",static_local_value); // default value is 0

}

我们在函数func中定义一个普通变量和static修饰的变量,并且都没有初始化它们。编译时会把static变量初始化为0,而不会初始化普通变量。下面是程序的运行结果,请参考:

temp = 134513922
static_local_value = 0 

从上面的程序运行结果中可以看到,static变量的默认值是0,而普通变量的默认值是不确定的。

对于函数来说,static不会影响它的生命周期,但是会缩小它的作用域,这点和static限定变量时的效果相同,因此,我就不多介绍了。

看官们,完整的代码放到了我的资源中,大家可以点击这里下载使用。

在编写代码的时候,我们经常使用static来限定变量和函数,主要是为了把它们的作用域缩小到一个文件内,这样做可以避免和其它文件中同名的变量或者函数发生命名冲突。

打个比方,据说国内叫张伟的人特别多,也就是说重名的人很多。如果我在这里叫张伟,那么可能只有一个看官叫张伟,毕竟在这里听我讲小说的看官们人数不是很多,如果我在网上发个帖子说:张伟中奖了。那么可能会有很多叫张伟的人去领奖,如何区分这么多张伟呢,使用static关键字来限定一下就行,哈哈。

各位看官,关于static关键字的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解 。


时间: 2024-10-20 04:01:30

一起talk C栗子吧(第一百二十六回:C语言实例--static关键字)的相关文章

一起talk C栗子吧(第一百二十二回:C语言实例--多线程)

各位看官们,大家好,上一回中咱们说的是线程知识体系图的例子,这一回咱们说的例子是:多线程.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我首先给大家拜个晚年,祝大家在新的一年里身体健康,万事如意. 今天我们介绍一下多线程,我相信大家都听过这个名词,但是具体的含义是什么呢?其实多线程是指两个或者两个以上的线程在一起运行,他们共同完成某个工作. 我们在前面的章回中介绍过使用pthread_create()函数去创建线程.如果想使用多线程,那么只需要多次使用该函数去创建线程就可以.接下来

第一百二十六节,JavaScript,XPath操作xml节点

第一百二十六节,JavaScript,XPath操作xml节点 学习要点: 1.IE中的XPath 2.W3C中的XPath 3.XPath跨浏览器兼容 XPath是一种节点查找手段,对比之前使用标准DOM去查找XML中的节点方式,大大降低了查找难度,方便开发者使用.但是,DOM3级以前的标准并没有就XPath做出规范:直到DOM3在首次推荐到标准规范行列.大部分浏览器实现了这个标准,IE则以自己的方式实现了XPath. 一.IE中的XPath 在IE8及之前的浏览器,XPath是采用内置基于A

一起talk C栗子吧(第一百二十四回:C语言实例--内置宏)

各位看官们,大家好,上一回中咱们说的是显示变量和函数地址的样例,这一回咱们说的样例是:内置宏.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在编译程序的时候,假设有语法错误,编译器就会提示,在某个文件的某一行有错误,这是怎么做到的呢?事实上是使用了C语言的内置宏. 说到宏,我想大家都知道,而所谓的内置宏相似于C语言的关键字,它是C语言自定义的,因此我们不须要定义宏,就能够直接使用.经常使用的内置宏有"_LINE_"和"_FILE_".假设把它们放到

一起talk C栗子吧(第一百五十六回:C语言实例--基于AF_UNIX域的流套接字通信)

各位看官们,大家好,上一回中咱们说的获取socket通信地址的例子,这一回咱们说的例子是:基于AF_UNIX域的流套接字通信 .闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在前面章回中介绍了套接字的通信过程以及套接字的的细节,总感觉还缺少些什么,一时还真是想不起来.这好比我们有了食谱也有了食材,那么我们就可以做一道美味的佳肴了.啊!有了.一提到美味的佳肴,灵感就来了.我们缺少的是对套接字的综合演练,也就是把前面章回中知识串在一起,然后举一个综合使用套接字知识进行套接字通信的例

一起talk C栗子吧(第一百三十二回:C语言实例--从内存的角度看进程和线程)

各位看官们,大家好,上一回中咱们说的C程序内存布局的例子,这一回咱们说的例子是:从内存的角度看进程和线程.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们刚刚介绍完C程序的内存布局,我们趁热打铁,从内存的角度来分析一下进程和线程. 不管是进程还是线程,他们都会加载到内存中才能运行,因此他们在内存中的布局和其它C程序的内存布局完全相同.进程和线程的内存布局也分为代码区,数据区,堆区和栈区. 对进程来说,父子进程只共享代码区中的内容,父子进程拥有各自的数据区,堆区和栈区.而且它们只能

一起talk C栗子吧(第一百五十二回:C语言实例--计算机中的大小端)

各位看官们,大家好,上一回中咱们说的是socket通信地址的例子,这一回咱们说的例子是:计算机中的大小端 .闲话休提,言归正转.让我们一起talk C栗子吧! 大小端据说来源于小说<格列佛游记>,书中说:人们在争论打开鸡蛋的方式是从鸡蛋的大端还是小端打开鸡蛋.争论不休,甚至还引起了战争.你说说,不管你从哪一端打开鸡蛋,打开的都是鸡蛋呀,这有什么可以争论的呢?还要通过战争来解决.大家不必关注这个争论,如果真想了解其中的细节,可以看看这部小说.不过在计算机中的大小端就不像小说中争论打开鸡蛋那么简单

一起talk C栗子吧(第一百五十九回:C语言实例--基于AF_INET域的数据报套接字通信)

各位看官们,大家好,上一回中咱们说的是基于AF_INET域的流套接字通信的例子,这一回咱们说的例子是:基于AF_INET域的数据报套接字通信 .闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在上一回中一起制作了我们的第三道佳肴是:基于AF_INET域的流套接字通信.今天,我将和大家一起制作第四道佳肴:基于AF_INET域的数据报套接字通信. 制作第四道佳肴的菜谱:数据报套接字过程. 制作第四道佳肴的食材:数据报套接字的接口,套接字属性,套接字地址信息. 看官们,以上的内容,我们

一起talk C栗子吧(第一百五十八回:C语言实例--基于AF_INET域的流套接字通信)

各位看官们,大家好,上一回中咱们说的是基于AF_UNIX域的数据报套接字通信的例子,这一回咱们说的例子是:基于AF_INET域的流套接字通信 .闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在上一回中一起制作了我们的第二道佳肴是:基于AF_UNIX域的数据报套接字通信.今天,我将和大家一起制作第三道佳肴:基于AF_INET域的流套接字通信. 制作第三道佳肴的菜谱:流套接字过程. 制作第三道佳肴的食材:流套接字的接口,套接字属性,套接字地址信息. 看官们,以上的内容,我们在前面章

一起talk C栗子吧(第一百五十四回:C语言实例--socket通信地址系统调用二)

各位看官们,大家好,上一回中咱们说的是socket通信地址系统调用的例子,这一回咱们继续说该例子.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在上一回介绍的通信地址系统调用有效地解决了数据存储方式的问题,不过,还有一个系统调用也可以解决这种问题,这一回我们将介绍该系统调用:getaddrinfo. 函数原型 该系统调用从其名字上看是用来获取地址的信息,这里的地址主要指套接字通信地址.它获取到的地址信息不需要进行字节序转换,我们可以直接用来进行套接字通信.不过,我们不能只看名字