C,C++中的static
在C和C++中,static都有两种基本的含义,并且这两种含义经常是互相有冲突的:
1) 在固定的地址上分配,也就是说对象是在一个特殊的静态数据区上创建的,而不是每次
函数调用时在堆栈上产生的。这也是静态存储的概念。
2) 对一个特定的编译单位来说是本地的(就像我们在后面将要看到的,这在C++中包括类
的范围)。这里static控制名字的可见性,所以这个名字在这个单元或类之外是不可见的。这也
描述了连接的概念,它决定连接器将看到哪些名字。
1.函数内部的静态变量
通常,在函数体内定义一个变量时,编译器使得每次函数调用时堆栈的指针向下移一个适
当的位置,为这些内部变量分配内存。如果这个变量有一个初始化表达式,那么每当程序运行
到此处,初始化就被执行。
然而,有时想在两次函数调用之间保留一个变量的值,我们可以通过定义一个全局变量来
实现这点,但这样一来,这个变量就不仅仅受这个函数的控制。C和C++都允许在函数内部创
建一个static对象,这个对象将存储在程序的静态数据区中,而不是在堆栈中。这个对象只在
函数第一次调用时初始化一次,以后它将在两次函数之间保持它的值。
如果没有为一个预定义类型的静态变量提供一个初始值的话,编译器会确保在程序开始时为它初始化为0(将转化为适当的类型)。
2.函数体内部的静态对象
用户自定义的静态变量同一般的静态对象的规则是一样的,而且它同样也必须有初始化操作。
但是,零赋值只对预定义类型有效,用户自定义类型必须用构造函数来初始化。因此,如果我们
在定义一个静态对象时没有指定构造函数参数,这个类就必须有缺省的构造函数。
tips:
在C++中,全局静态对象的构造函数是在main()之前调用的,所以我们现在有了一个在进
入main()之前执行一段代码的简单的、可移植的方法,并且可以在退出main()之后用析构函数
执行代码。在C中要做到这一点,我们不得不熟悉编译器开发商的汇编语言的开始代码。
3.控制连接
一般情况下,在文件范围内的所有名字(既不嵌套在类或函数中的名字)对程序中的所有
编译单元来说都是可见的。这就是所谓的外部连接,因为在连接时这个名字对连接器来说是可
见的,外部的编译单元、全局变量和普通函数都有外部连接。
有时我们可能想限制一个名字的可见性。想让一个变量在文件范围内是可见的,这样这个
文件中的所有函数都可以使用它,但不想让这个文件之外的函数看到或访问该变量,或不想这
个变量的名字与外部的标识符相冲突。
在文件范围内,一个被明确声明为static的对象或函数的名字对编译单元(一个.cpp文件)来说是局部变量;这些名字有内部连接。这意味着我们可以在其他的编译单元中使用同样的名字,而不会发生名字冲突。
内部连接的一个好处是这个名字可以放在一个头文件中而不用担心连接时发生冲突。那些
通常放在头文件里的名字,像常量、内联函数( inline function),在缺省情况下都是内部连接
的(当然常量只有在C + +中缺省情况下是内部连接的,在C中它缺省为外部连接)。注意连接只
引用那些在连接/装载期间有地址的成员,因此类声明和局部变量并没有连接。
• 冲突问题
下面例子说明了static的两个含义怎样彼此交叉的。所有的全局对象都是隐含为静态存储类,
所以如果我们定义(在文件范围)
int a=0;
则a被存储在程序的静态数据区,在进入main()函数之前,a即已初始化了。另外,a对全局都是可
见的,包括所有的编译单元。用可见性术语,s t a t i c(只在编译单元内可见)的反义是e x t e r n,它
表示这个名字对所有的编译单元都是可见的。所以上面的定义和下面的定义是相同的。
extern int a=0;
但如果这样定义:
static int a=0;
我们只不过改变了a的可见性,现在a成了一个内部连接。但存储类型没有改变—对象总是驻
留在静态数据区,而不管是s t a t i c还是e x t e r n。
一旦进入局部变量,s t a t i c就不会再改变变量的可见性(这时e x t e r n是没有意义的),而只
是改变变量的存储类型。
对函数名,s t a t i c和e x t e r n只会改变它的可见性,所以如果说:
extern void f();
它和没有修饰时的声明是一样的:
void f();
如果定义:
static void f();
它意味着f ( )只在本编译单元内是可见的,这有时称作文件静态。
4.其他的存储类型指定符
我们会看到s t a t i c和e x t e r n用得很普遍。另外还有两个存储类型指定符,这两种用得较少。
一个是a u t o ,人们几乎不用它,因为它告诉编译器这是一个局部变量,实际上编译器总是可以从
变量定义时的上下文中判断出这是一个局部变量。所以a u t o是多余的。还有一个是r e g i s t e r,它
也是局部变量,但它告诉编译器这个特殊的变量要经常用到,所以编译器应该尽可能地让它保
存在寄存器中。它用于优化代码。各种编译器对这种类型的变量处理方式也不尽相同,它们有
时会忽略这种存储类型的指定。一般,如果要用到这个变量的地址, r e g i s t e r指定符通常都会被
忽略。应该避免用r e g i s t e r类型,因为编译器在优化代码方面通常比我们做得更好。
C,C++中的static的更多相关文章
- Android 中关于static的使用问题
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/5251564.html 项目中,在不停地接收串口数据很长一段时间(几小时)后,会偶然性的报错.初步排除了oom ...
- (转)Java中的static关键字解析
转载: http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: &q ...
- 关于Java中的static关键字
Java中的 static 关键字,确实是一个关键的字(key word),今天就来总结一下它的用法,说说为什么关键. Java中的 static 关键字主要是用来做内存管理的.理解了这句话才能够比较 ...
- Java中的static关键字解析
Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...
- C++中的static关键字的总结
C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用. 1.面向过程设计中的st ...
- java中的static使用--静态变量、静态方法
Java 中的 static 使用之静态变量 大家都知道,我们可以基于一个类创建多个该类的对象,每个对象都拥有自己的成员,互相独立.然而在某些时候,我们更希望该类所有的对象共享同一个成员.此时就是 s ...
- (转)Java中的static关键字解析
转自http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: “sta ...
- Java中的static的使用
Java中的static使用之静态变量 神话丿小王子的博客主页 1.Java 中被static修饰的成员称为静态成员或类成员.它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享.且优先于对象 ...
- java中的static详解
如果一个类成员被声明为static,它就能够在类的任何对象创建之前被访问,而不必引用任何对象.static 成员的最常见的例子是main( ) .因为在程序开始执行时必须调用main() ,所以它被声 ...
- Java 中的 static 使用之静态变量
大家都知道,我们可以基于一个类创建多个该类的对象,每个对象都拥有自己的成员,互相独立.然而在某些时候,我们更希望该类所有的对象共享同一个成员.此时就是 static 大显身手的时候了!! Java 中 ...
随机推荐
- 与众不同 windows phone (28) - Feature(特性)之手机方向, 本地化, 应用程序的试用体验, 系统主题资源, 本地数据的加密解密
原文:与众不同 windows phone (28) - Feature(特性)之手机方向, 本地化, 应用程序的试用体验, 系统主题资源, 本地数据的加密解密 [索引页][源码下载] 与众不同 wi ...
- linux route命令的使用详解
route命令用于显示和操作IP路由表.要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现.在Linux系统中,设置路由通常是 为了解决以下问题:该Linu ...
- c++中虚函数和纯虚函数定义
只有用virtual声明类的成员函数,使之成为虚函数,不能将类外的普通函数声明为虚函数.因为虚函数的作用是允许在派生类中对基类的虚函数重新定义.所以虚函数只能用于类的继承层次结构中. 一个成员函数被声 ...
- C语言之基本算法35—数组上三角之积 主对角之积 副对角之积
//数组算法 /* ============================================================= 题目:求四阶矩阵上三角之积.主对角之积,副对角之积: 如 ...
- 改动Oracle GoldenGate(ogg)各个进程的读检查点和写检查点
请注意:请谨慎改动Oracle GoldenGate(ogg)各个进程的读检查点和写检查点. 请确保已经 掌握 ogg 各个进程的读检查点和写检查点的详细含义. BEGIN {NOW | yyyy-m ...
- [置顶] 深圳华为BSS公共部件 (BI 商业智能 Java Javascript)
深圳华为BSS公共部件 部门招聘 招聘面试地点:大连,西安 工作地点:深圳 时间:2013年9月7日 联系方式:dawuliang@gmail.com 18675538182 有兴趣的同学,可以直接电 ...
- 14.3.5.2 Deadlock Detection and Rollback 死锁检测和回滚:
14.3.5.2 Deadlock Detection and Rollback 死锁检测和回滚: InnoDB 自动检查四艘,回滚一个事务或者事务来打破死锁. InnoDB 试图选择小的事务来回滚, ...
- zoj 2972 - Hurdles of 110m
题目:110米栏,运动员能够用三种状态跑,1状态耗体力且跑得快,2状态不消耗体力,3状态恢复体力且跑得慢. 体力上限是M,且初始满体力,如今想知到最小的时间跑全然程. 分析:dp,全然背包.题目是一个 ...
- 《算法导论》 — Chapter 7 高速排序
序 高速排序(QuickSort)也是一种排序算法,对包括n个数组的输入数组.最坏情况执行时间为O(n^2). 尽管这个最坏情况执行时间比較差.可是高速排序一般是用于排序的最佳有用选择.这是由于其平均 ...
- zzu--2014年11月16日月潭赛 B称号
1229: Rational Resistance Time Limit: 1 Sec Memory Limit: 128 MB Submit: 8 Solved: 4 [id=1229" ...