首页 > 其他分享 >c语言static(c语言static是什么意思)

c语言static(c语言static是什么意思)

时间:2022-10-24 19:07:56浏览次数:57  
标签:file2 file1 语言 局部变量 printStr 意思 static 函数


怎样把C语言学好怎样把C语言学好?怎样把C语言学好怎样把C语言学

重要的是急不了的,要一步一步来,慢慢来,把每个知识都学好,烂熟于心,到时就能灵活运用,加油吧孩子。不难的,打好基础

什么是C语言

C语言是一种计算机程序设计语言。它既有高级语言的特点,又具有汇编语言的特点。它可以作为系统设计语言,编写工作系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。因此,它的应用范围广泛。

c语言static的用法

放在函数内部的static变量互相不会影响,两个static变量是分别独立存在的。

如果您需要它们互相影响,那么应该定义为全局的,放在函数之外。static 型变量只初始化一次,第一次调用fun函数时,f初始化为1,运行完后f仍为1;第二次调用时f的值还是1,不再初始化,于是f在fun运行完后变为2,这样依次完成所有循环,每次计算f时,都沿用上一个循环的f值

C语言中static 的详细说明。

google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大论不知所云要么在关键之处几个字略过,对于想挖掘底层原理的初学者来说参考性不是很大。所以,我这篇博文博采众家之长,把互联网上的资料整合归类,并亲手编写程序验证之。

C语言代码是以文件为单位来组织的,在一个源程序的所有源文件中,一个外部变量(注意不是局部变量)或者函数只能在一个源程序中定义一次,如果有重复定义的话编译器就会报错。伴随着不同源文件变量和函数之间的相互引用以及相互独立的关系,产生了extern和static关键字。

下面,详细分析一下static关键字在编写程序时有的三大类用法:

一,static全局变量

我们知道,一个进程在内存中的布局如图1所示:

其中.text段保存进程所执行的程序二进制文件,.data段保存进程所有的已初始化的全局变量,.bss段保存进程未初始化的全局变量(其他段中还有很多乱七八糟的段,暂且不表)。在进程的整个生命周期中,.data段和.bss段内的数据时跟整个进程同生共死的,也就是在进程结束之后这些数据才会寿终就寝。

当一个进程的全局变量被声明为static之后,它的中文名叫静态全局变量。静态全局变量和其他的全局变量的存储地点并没有区别,都是在.data段(已初始化)或者.bss段(未初始化)内,但是它只在定义它的源文件内有效,其他源文件无法访问它。所以,普通全局变量穿上static外衣后,它就变成了新娘,已心有所属,只能被定义它的源文件(新郎)中的变量或函数访问。

以下是一些示例程序

file1.h如下:

[cpp] view plaincopy

#include

void printStr();

我们在file1.c中定义一个静态全局变量hello, 供file1.c中的函数printStr访问.

[cpp] view plaincopy

#include "file1.h"

static char* hello = "hello cobing!";

void printStr()

printf("%s\n", hello);

file2.c是我们的主程序所在文件,file2.c中如果引用hello会编译出错

[cpp] view plaincopy

#include "file1.h"

int main()

printStr();

printf("%s\n", hello);

return 0;

报错如下:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2

file2.c: In function ‘main’:

file2.c:6: 错误:‘hello’ 未声明 (在此函数内第一次使用)

file2.c:6: 错误:(即使在一个函数内多次出现,每个未声明的标识符在其

file2.c:6: 错误:所在的函数内只报告一次。)

如果我们将file2.c改为下面的形式:

[cpp] view plaincopy

#include "file1.h"

int main()

printStr();

return 0;

则会顺利编译连接。

运行程序后的结果如下:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2

[liujx@server235 static]$ ./file2

hello cobing!

上面的例子中,file1.c中的hello就是一个静态全局变量,它可以被同一文件中的printStr调用,但是不能被不同源文件中的file2.c调用。

二,static局部变量

普通的局部变量在栈空间上分配,这个局部变量所在的函数被多次调用时,每次调用这个局部变量在栈上的位置都不一定相同。局部变量也可以在堆上动态分配,但是记得使用完这个堆空间后要释放之。

static局部变量中文名叫静态局部变量。它与普通的局部变量比起来有如下几个区别:

1)位置:静态局部变量被编译器放在全局存储区.data(注意:不在.bss段内,原因见3)),所以它虽然是局部的,但是在程序的整个生命周期中存在。

2)访问权限:静态局部变量只能被其作用域内的变量或函数访问。也就是说虽然它会在程序的整个生命周期中存在,由于它是static的,它不能被其他的函数和源文件访问。

3)值:静态局部变量如果没有被用户初始化,则会被编译器自动赋值为0,以后每次调用静态局部变量的时候都用上次调用后的值。这个比较好理解,每次函数调用静态局部变量的时候都修改它然后离开,下次读的时候从全局存储区读出的静态局部变量就是上次修改后的值。

以下是一些示例程序:

file1.h的内容和上例中的相同,file1.c的内容如下:

[cpp] view plaincopy

#include "file1.h"

void printStr()

int normal = 0;

static int stat = 0;//this is a static local var

printf("normal = %d ---- stat = %d\n",normal, stat);

normal++;

stat++;

为了便于比较,我定义了两个变量:普通局部变量normal和静态局部变量stat,它们都被赋予初值0;

file2.c中调用file1.h:

[cpp] view plaincopy

#include "file1.h"

int main()

printStr();

printStr();

printStr();

printStr();

printf("call stat in main: %d\n",stat);

return 0;

这个调用会报错,因为file2.c中引用了file1.c中的静态局部变量stat,如下:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2

file2.c: In function ‘main’:

file2.c:9: 错误:‘stat’ 未声明 (在此函数内第一次使用)

file2.c:9: 错误:(即使在一个函数内多次出现,每个未声明的标识符在其

file2.c:9: 错误:所在的函数内只报告一次。)

编译器说stat未声明,这是因为它看不到file1.c中的stat,下面注掉这一行:

[cpp] view plaincopy

#include "file1.h"

int main()

printStr();

printStr();

printStr();

printStr();

// printf("call stat in main: %d\n",stat);

return 0;

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2

[liujx@server235 static]$ ./file2

normal = 0 ---- stat = 0

normal = 0 ---- stat = 1

normal = 0 ---- stat = 2

normal = 0 ---- stat = 3

运行如上所示。可以看出,函数每次被调用,普通局部变量都是重新分配,而静态局部变量保持上次调用的值不变。

需要注意的是由于static局部变量的这种特性,使得含静态局部变量的函数变得不可重入,即每次调用可能会产生不同的结果。这在多线程编程时可能会成为一种隐患。需要多加注意。

三,static函数

相信大家还记得C++面向对象编程中的private函数,私有函数只有该类的成员变量或成员函数可以访问。在C语言中,也有“private函数”,它就是接下来要说的static函数,完成面向对象编程中private函数的功能。

当你的程序中有很多个源文件的时候,你肯定会让某个源文件只提供一些外界需要的接口,其他的函数可能是为了实现这些接口而编写,这些其他的函数你可能并不希望被外界(非本源文件)所看到,这时候就可以用static修饰这些“其他的函数”。

所以static函数的作用域是本源文件,把它想象为面向对象中的private函数就可以了。

下面是一些示例:

file1.h如下:

[cpp] view plaincopy

#include

static int called();

void printStr();

file1.c如下:

[cpp] view plaincopy

#include "file1.h"

static int called()

return 6;

void printStr()

int returnVal;

returnVal = called();

printf("returnVal=%d\n",returnVal);

file2.c中调用file1.h中声明的两个函数,此处我们故意调用called():

[cpp] view plaincopy

#include "file1.h"

int main()

int val;

val = called();

printStr();

return 0;

编译时会报错:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2

file1.h:3: 警告:‘called’ 使用过但从未定义

/tmp/ccyLuBZU.o: In function `main':

file2.c:(.text+0x12): undefined reference to `called'

collect2: ld 返回 1

因为引用了file1.h中的static函数,所以file2.c中提示找不到这个函数:undefined reference to 'called'

下面修改file2.c:

[cpp] view plaincopy

#include "file1.h"

int main()

printStr();

return 0;

编译运行:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2

[liujx@server235 static]$ ./file2

returnVal=6

static函数可以很好地解决不同原文件中函数同名的问题,因为一个源文件对于其他源文件中的static函数是不可见的。static 用来说明静态变量。

如果是在函数外面定义的,那么其效果和全局变量类似,但是,static定义的变量只能在当前c程序文件中使用,在另一个c代码里面,即使使用extern关键词也不能访问这个static变量。

如果是在函数内部定义的,那么这个变量只初始化一次,即使再次调用这个函数,这个static变量也不会再次被初始化,于是,这个变量的取值就会一直保存着,也就是说,当你再次调用这个函数的时候,里面用到这个static变量时,就会发现,还是它还是上一次函数调用时的结果。静态变量,就是在定义的时候,有static 修饰的变量,形式为

static TYPE var_name = init_value;

而动态变量,形式为

TYPE var_name = init_value;

即没有static 修饰。其中的=init_value均可省略。

区分定义在函数外的全局变量,和函数内的局部变量,作用域,生命周期,及无显式初始化时的初始值,均有区别。

1 动态全局变量:

作用域为整个项目,即最终编译成可执行文件的所有文件中均可以使用动态全局变量。

生命周期为从程序运行到程序退出,即贯穿整个运行时间。

无显式初始化时默认初始化值为0。

2 静态全局变量:

作用域为当前文件,从定义/声明位置到文件结尾。

生命周期为从程序运行到程序退出,即贯穿整个运行时间。

无显式初始化时默认初始化值为0。

3 动态局部变量:

作用域为当前函数,从定义位置,到其所在的{}的结束位置。

生命周期为从函数调用到函数退出。

无显式初始化时默认初始化值为随机值。

4 静态局部变量:

作用域为当前函数,从定义位置,到其所在的{}的结束位置。

生命周期为从程序运行到程序退出,即贯穿整个运行时间,当下次函数调用时,静态局部变量不会被再次初始化,而是沿用上次函数退出时的值。

无显式初始化时默认初始化值为0。

标签:file2,file1,语言,局部变量,printStr,意思,static,函数
From: https://blog.51cto.com/yetaotao/5790922

相关文章

  • c语言判断闰年(c语言判断闰年个数)
    闰年的判断方法请问怎么判断那一年是闰年,比如2004是闰年吗??同时满足以下条件:1、年份能被4整除;2、年份若是100的整数倍的话,需被400整除,否则是平年怎样判断平年和闰年???????......
  • c语言冒泡排序法代码(c语言冒泡排序法代码讲解)
    求一个C语言冒泡排序法的简单程序怎么办?  下一趟排序开始时,R[1。。lastExchange-1]是有序区,R[lastExchange。。n]是无序区。这样,一趟排序可能使当前有序区扩充多个记录,从......
  • c语言小游戏(c语言小游戏代码飞机大战)
    怎样用C语言编写一个小游戏?“贪吃蛇”C代码:#include#include#include#include#include#defineW78 //游戏框的宽,x轴#defineH26 //游......
  • c语言strlen(c语言strlen计算空格吗)
    c语言里面的strlen是干什么的strlen()是计算字符串长度的函数,将返回从字符串首到'\0'之间总共的字符个数,原型为:externunsignedintstrlen(char*s);所以除非你的a[0]本身......
  • c语言学习资料
    在大二学习了c语言基础教程不请出以后应看先什么资料要是想考二级的话就看看c公共基础和南开一百题我保证只要这两个你看会了七成就能过二级要是想深入学习我就不了解了。......
  • c语言关键字(c语言关键字volatile)
    什么是C语言关键字关键字又称保留字,是c语言预定义的单词,在程序中有不同的使用目的,在定义标识符的时候,不能使用这些关键字,否则在编译时会产生莫名其妙的错误,C语言由ANSI定义......
  • c语言helloworld代码(c语言helloworld代码编写)
    C语言:求代码#includeintmain()inta,b,c,d,t,max,min;printf("Enterfourintegers:");scanf("%d%d%d%d",&a,&b,&c,&d);if(ad)min=d;printf("Largest:%d\nS......
  • 自然语言处理学习笔记-lecture09-篇章分析
    自然语言处理的处理单元分为字(编码、输入法),词、短语(形态分析、汉语分词、词性标注、词义消歧、命名实体识别等),句子(句法分析、语块分析、语义角色标注),篇章(机器翻译、......
  • go语言基础语法
    声明变量 varidentifiertypevar:声明变量关键字identifier:变量名称type:变量类型批量声明及初始化 var( name string="dcl" phonein......
  • c语言爱心代码(c语言画爱心的代码)
    html代码和c语言等编程语言有什么联系吗?HTML叫做超文本标记语言(标准通用标记语言下的一个应用)或超文本链接标示语言,是目前网络上应用最为广泛的语言,也是构成网页文档的主......