函数c语言中的static关键字

c语言static  时间:2021-02-28  阅读:()

网上的几个介绍 引用在这里stati c关键字是C, C++中都存在的关键字,它主要有三种使用方式,其中前两种在C/C++语言中使用,第三种只在C++中使用(C,C++中具体细微操作不尽相同,本文以C++为准) .

(1)局部静态变量

(2)外部静态变量/函数

(3)静态数据成员/成员函数

下面就这三种使用方式及注意事项分别说明

一、局部静态变量

在C/C++中,局部变量按照存储形式可分为三种auto, stati c, register

(<C语言程序设计(第二版)>谭浩强, 第174-175页)

与auto类型(普通)局部变量相 比, stati c局部变量有三点不同

1.存储空间分配不同auto类型分配在栈上,属于动态存储类别, 占动态存储区空间, 函数调用结束后自动释放,而stat ic分配在静态存储区 ,在程序整个运行期间都不释放.两者之间的作用域相同 ,但生存期不同.

2. stati c局部变量在所处模块在初次运行时进行初始化工作,且只操作一次

3.对于局部静态变量,如果不赋初值,编译期会自动赋初值0或空字符,而auto类型的初值是不确定的. (对于C++中的cla ss对象例外, class的对象实例如果不初始化,则会自动调用默认构造函数,不管是否是stati c类型)

特点: stati c局部变量的”记忆性”与生存期的 ”全局性”

所谓”记忆性”是指在两次函数调用时,在第二次调用进入时, 能保持第一次调用退出 时的值.

示例程序一

#include <iostream>using namespace std;void stati cLoca lVar()

{stati c int a = 0; //运行期时初始化一次,下次再调用 时,不进行初始化工作cout<<"a="<<a<<endl ;

++a;

}int main()

{s tat i cLoca lVar() ; //第一次调用,输出a=0s tat i cLoca lVar() ; //第二次调用,记忆了第一次退出时的值,输出a=1return 0;

}

应用:

利用”记忆性” , 记录函数调用的次数(示例程序一)

利用生存期 的”全局性” , 改善” return a pointer / reference to a local object”的问题. Local objec t的问题在于退出函数,生存期即结束, .利用static的作用,延长变量的生存期.

示例程序二:

// IP addre ss to strin g format

// Used in Ethernet Frame and IP Header analy sisconst char * IpToS tr(UINT32 IpAddr)

{stati c char strBu ff[16] ; // stati c局部变量,用于返回地址有效const unsig ned char *pChIP = (const unsigned char *)&IpAdd r;sprin tf(strBu ff, "%u.%u.%u.%u", pChIP [0], pChIP [1], pChIP [2], pChIP [3]) ;return strBuff;

}

注意事项:

1. “记忆性”,程序运行很重要的一点就是可重复性,而stat ic变量的”记忆性”破坏了这种可重复性,造成不同时刻至运行的结果可能不 同.

2. “生存期”全局性和唯一性.普通的local变量的存储空间分配在stack上, 因此每次调用函数时, 分配的空间都可能不一样,而stat ic具有全局唯一性的特点,每次调用时,都指向同一块内存,这就造成一个很重要的 问题----不可重入性! ! !

这样在多线程程序设计或递归程序设计中, 要特别注意这个问题.

(不可重入性的例子可以参见<effec tive C++ (2nd)>(影印版)第103-105页)

下面针对示例程序二,分析在多线程情况下的不安全性. (为方便描述,标上行号)

①const char * IpToS tr(UINT32 IpAddr)

②{

③ stati c char strBu ff[16] ; // stati c局部变量,用于返回地址有效

④ const unsig ned char *pChIP = (const unsigned char *)&IpAdd r;

⑤ sprin tf(strBu ff, "%u.%u.%u.%u", pChIP [0], pChIP [1], pChIP[2], pChIP [3]) ;

⑥ return strBuff;

⑦}

假设现在有两个线程A,B运行期间都需要调用 IpToS tr()函数,将32位的IP地址转换成点分1 0进制的字符串形式. 现A先获得执行机会,执行IpT oStr(),传入的参数是0x0B 090A0 A,顺序执行完应该返回的指针存储区 内容是: ” 10. 10.9. 11” ,现执行到⑥时, 失去执行权,调度到B线程执行, B线程传入的参数是0 xA8A8 A8C0, 执行至⑦,静态存储区 的内容是1 92. 168. 168. 168.当再调度到A执行时, 从⑥继续执行, 由于strBuff的全局唯一性,内容已经被B线程冲掉,此时返回的将是192 . 168. 168. 168字符串,不再是10. 10.9. 11字符串 .

二、外部静态变量函数

在C中static有了第二种含义用来表示不 能被其它文件访问的全局变量和函数。,但为了限制全局变量/函数的作用域,函数或变量前加static使得函数成为静态函数。但此处“static”的含义不是指存储方式而是指对函数的作用域仅局限于本文件(所以又称内部函数) 。注意此时,对于外部(全局)变量, 不论是否有stati c限制, 它的存储区域都是在静态存储区,生存期都是全局的. 此时的st atic只是起作用域限制作用, 限定作用域在本模块(文件)内部.

使用内部函数的好处是不同的人编写不同的函数时不用担心自己定义的函数是否会与其它文件中的 函数同名。

示例程序三:

//f i l e 1 .cppstati c int varA;int varB;

extern void funA()

{

„„

}stati c void funB()

{

„„

}

//f i l e2.cppextern int varB; //使用fil e1.cpp中定义的全局变量exter n int varA; //错误! varA是stati c类型,无法在其他文件中使用extern vod funA() ; //使用fil e1.cpp中定义的函数exter n void funB() ; //错误!无法使用f ile1. cpp文件中stat ic函数

三、静态数据成员成员函数(C++特有)

C++重用了这个关键字并赋予它与前面不同的第三种含义表示属于一个类而不是属于此类的任何特定对象的变量和函数.这是与普通成员函数的最大区别,也是其应用所在, 比如在对某一个类的对象进行计数时,计数生成多少个类的实例,就可以用到静态数据成员.在这里面,stati c既不是限定作用域的,也不是扩展生存期的作用,而是指示变量/函数在此类中的唯一性.这也是”属于一个类而不是属于此类的任何特定对象的变量和函数”的含义. 因为它是对整个类来说是唯一的, 因此不可能属于某一个实例对象的. (针对静态数据成员而言,成员函数不

管是否是s tatic,在内存中只有一个副本,普通成员函数调用时,需要传入t his指针, static成员函数调用时, 没有thi s指针. )

请看示例程序四(<effec tive c++ (2nd)>(影印版)第59页)class Enemy Targe t {publi c:

EnemyTarge t() { ++numTa rgets ; }

Enemy Targe t(const Enemy Targe t&) { ++numTa rgets ; }

~Enemy Targe t() { --numTa rgets ; }stati c size_t numbe rOfTargets () { return numTa rgets ; }bool destroy() ; // returns succe ss of attempt to destroy EnemyTarge t objectpriva te:stati c size_t numTargets ; // object count er

} ;

// class stati cs must be defined outside the class ;

// initialization is to 0 by defaultsize_t Enemy Targe t: :numTa rgets ;

在这个例子中,静态数据成员numT arget s就是用来计数产生的对象个数的 .

另外, 在设计类的多线程操作时, 由于POS IX库下的线程函数p threa d_cre ate()要求是全局的,普通成员函数无法直接做为线程函数,可以考虑用Stati c成员函数做线程函数.

【我解C语言面试题系列 】001 stati c有什么用途

【题目】 stati c有什么用 途

在网上流传很广的一个答案是

1、限制变量的作用域

2、设置变量的存储域

我觉得这样答题是不妥当的有点文不对题的感觉。

下面是我给出的答案stati c类型声明符在C语言里面主要有三个用途

<!--[if !suppo rtLis ts]-->1、 <!--[endif]-->声明静态局部变量。

<!--[if !suppo rtLis ts]-->2、 <!--[endif]-->声明静态外部全局变量。

<!--[if !suppo rtLis ts]-->3、 <!--[endif]-->声明静态外部函数。

下面是我整理的有关上面三个用法的解释说明。另外网友x iaoca i0001的

《stati c用法小结》一文有更详细的解释请参考。

[url]http://blog. csdn.net/xiaoc ai000 1/archi ve/2006/04/14/66292 1.aspx[/url]静态局部变量与auto对比

<!--[if !suppo rtLis ts]-->1、 <!--[endif]-->存储空间分配、作用域和生存期stati c分配在静态存储区作用域仅仅限于声明该变量的函数内部。在程序整个运行期间都不释放生存期贯穿于程序运行的整个过程。auto类型分配在栈上属于动态存储类别 占动态存储区空间作用域仅仅限于声明该变量的函数内部。函数调用结束后自动释放生存期不过是在声明该变量的函数内部。

2、赋初值时的处理方式stati c静态局部变量在编译时赋初值 即只赋初值一次auto自动变量赋初值是在函数调用时进行每调用一次函数重新给一次初值相当于执行一次赋值语句。

3、未赋初值时的处理方式

如果在定义局部变量时不赋初值的话

stati c静态局部变量编译时自动赋初值0 对数值型变量或空字符对字符变量 。auto自动变量如果不赋初值则它的值是一个不确定的值。

静态外部全局变量

在C语言中stati c还用来声明静态外部全局变量那么这个全局变量的作用域就被限制在本文件内部。

外部变量即全局变量是在函数的外部定义的它的作用域为从变量定义处开始到本程序文件的末尾。如果外部变量不在文件的开头定义其有效的作用范围只限于定义处到文件终了。如果在定义点之前的函数想引用该外部变量则应该在引用之前用关键字ext ern对该变量作“外部变量声明” 。表示该变量是一个已经定义的外部变量。有了此声明就可以从“声明”处起合法地使用该外部变量。

而如果我们声明的全局变量不想被其他文件访问和使用又该怎么办

那就是在声明的时候前面加上关键字stat ic。

静态外部函数

在C语言中我们的函数默认都是全局的也就是说你可以调用其他文件中的函数。在使用的时候我们象前面一样在头文件中加上e xtern就可以了。但是有时候我们写的函数并不想让别的文件访问和调用那么我们在声明函数的时候前面加上stat ic就可以了。

使用内部函数的好处有二

1、可以让某些内部函数不为人所能使用而仅仅让调用者使用他能使用的东西有利于保护代码。

2、不同的人编写不同的函数时不用担心自己定义的函数是否会与其它文件中的函数同名

vpsdime:夏日促销活动,美国达拉斯VPS,2G内存/2核/20gSSD/1T流量,$20/年

vpsdime怎么样?vpsdime是2013年注册的国外VPS主机商,实际上他还有一系列的其他域名站点如Winity.io, Backupsy,Cloudive, Virtora等等,母公司“Nodisto IT”相对来说还是很靠谱了的商家。VPSDime主要提供各种高配低价VPS套餐,其中Linux VPS和存储VPS基于OpenVZ架构,高级VPS基于KVM。VPSDime在上个季度的Low...

DiyVM(50元起)老牌商家,香港沙田CN2直连vps/不限流量/五折终身优惠

diyvm怎么样?diyvm是一家国内成立时间比较久的主机商家了,大约在6年前站长曾经用过他家的美国机房的套餐,非常稳定,适合做站,目前商家正在针对香港沙田机房的VPS进行促销,给的是五折优惠,续费同价,香港沙田机房走的是CN2直连的线路,到大陆地区的速度非常好,DiyVM商家采用小带宽不限流量的形式,带宽2Mbps起步,做站完全够用,有需要的朋友可以入手。diyvm优惠码:五折优惠码:OFF50...

提速啦(24元/月)河南BGP云服务器活动 买一年送一年4核 4G 5M

提速啦的来历提速啦是 网站 本着“良心 便宜 稳定”的初衷 为小白用户避免被坑 由赣州王成璟网络科技有限公司旗下赣州提速啦网络科技有限公司运营 投资1000万人民币 在美国Cera 香港CTG 香港Cera 国内 杭州 宿迁 浙江 赣州 南昌 大连 辽宁 扬州 等地区建立数据中心 正规持有IDC ISP CDN 云牌照 公司。公司购买产品支持3天内退款 超过3天步退款政策。提速啦的市场定位提速啦主...

c语言static为你推荐
discuznt请问谁有Discuz!NT的QQ群?云播怎么看片手机云播怎么用?公章制作制作公章尺寸标准大小,字体,字号?安卓应用平台app应用平台有哪些 应用平台哪些xp系统停止服务Windowsxp系统为什么停止服务免费qq空间装扮有办法免费装扮QQ空间吗??宕机人们说的宕机是什么意思blogcnblogcn的博客可以搬家到哪些网站?rewritebase为什么我写.htaccess这个 rewriterule 进入死循环了,高手帮忙修改php购物车PHP中用json实现购物车功能,怎么实现
广西虚拟主机 万网域名证书查询 便宜域名 美国便宜货网站 win8升级win10正式版 帽子云 百度云1t 电信主机 卡巴斯基是免费的吗 卡巴斯基免费试用版 免费邮件服务器 starry 国内域名 阿里云个人邮箱 789电视剧网 重庆联通服务器托管 easypanel 电信测速器在线测网速 9929 更多