在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的更多相关文章

  1. Android 中关于static的使用问题

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/5251564.html 项目中,在不停地接收串口数据很长一段时间(几小时)后,会偶然性的报错.初步排除了oom ...

  2. (转)Java中的static关键字解析

    转载: http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: &q ...

  3. 关于Java中的static关键字

    Java中的 static 关键字,确实是一个关键的字(key word),今天就来总结一下它的用法,说说为什么关键. Java中的 static 关键字主要是用来做内存管理的.理解了这句话才能够比较 ...

  4. Java中的static关键字解析

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  5. C++中的static关键字的总结

    C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用. 1.面向过程设计中的st ...

  6. java中的static使用--静态变量、静态方法

    Java 中的 static 使用之静态变量 大家都知道,我们可以基于一个类创建多个该类的对象,每个对象都拥有自己的成员,互相独立.然而在某些时候,我们更希望该类所有的对象共享同一个成员.此时就是 s ...

  7. (转)Java中的static关键字解析

    转自http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: “sta ...

  8. Java中的static的使用

    Java中的static使用之静态变量 神话丿小王子的博客主页 1.Java 中被static修饰的成员称为静态成员或类成员.它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享.且优先于对象 ...

  9. java中的static详解

    如果一个类成员被声明为static,它就能够在类的任何对象创建之前被访问,而不必引用任何对象.static 成员的最常见的例子是main( ) .因为在程序开始执行时必须调用main() ,所以它被声 ...

  10. Java 中的 static 使用之静态变量

    大家都知道,我们可以基于一个类创建多个该类的对象,每个对象都拥有自己的成员,互相独立.然而在某些时候,我们更希望该类所有的对象共享同一个成员.此时就是 static 大显身手的时候了!! Java 中 ...

随机推荐

  1. 动态创建按钮的JS

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML>  <HEA ...

  2. CountDownLatch和CyclicBarrier的区别(转)

    在网上看到很多人对于CountDownLatch和CyclicBarrier的区别简单理解为CountDownLatch是一次性的,而CyclicBarrier在调用reset之后还可以继续使用.那如 ...

  3. 事务不提交,也有可能写redo和数据文件

    事务不提交,也有可能写redo和数据文件

  4. 日交易41.9亿,B2B的魅力为何不输于B2C、C2C?

        在最近两年的电子商务版图中,B2C和C2C可谓大放异彩,相比之下,B2B却显得颇为“低调”,当然,低调并不代表没有影响力,只不过,相比B2C和C2C面向数亿网民而言,B2B只针对企业和商家服务 ...

  5. OC-Protocol实现业务代理

    创建一个Protocol,相当于java的接口,但,有些方法不必实现,例如以下 #import <Foundation/Foundation.h> @protocol MyProtocol ...

  6. 如何做程序猿SOHO它定购家庭赚外快?

    做为一名程序猿.我想大多数人除了平时削尖了脑袋研究各种各样的技术之外. ArticleId=28404183" width="1" height="1" ...

  7. Struts2 学习第一步准备工作

    第一步:安装下载MyEclispe10 对于MyEclispe的下载安装就不再详述了. 第二步:下载Struts-2.3.15 Struts-2.3.15下载地址: http://struts.apa ...

  8. ConditonHelper

    在网上其实已经有很多类似这种拼接sql条件的类,但是没有看到一个让我感觉完全满意的这样的类.最近看到 http://www.cnblogs.com/xtdhb/p/3811956.html 这博客,觉 ...

  9. redis作为mysql的缓存服务器(读写分离) (转)

    一.redis简介Redis是一个key-value存储系统.和Memcached类似,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录 ...

  10. poj3252(数位dp)

    题目连接:http://poj.org/problem?id=3252 题意:拆成2进制,在记录0和1的个数 求区间[a,b]中,满足传化成2进制后,0的个数>=1的个数的数字的个数... 分析 ...