您的位置:首页 > 其它

auto、static、register、extern

2016-01-14 10:50 211 查看

auto关键字

auto对象和变量被存储在中,它的生命周期仅存在于它的声明所在的块(block)中。在块中定义的块如果不加其它的修饰符则都是auto类型的。auto关键字可以省去。auto对象和变量对外部模块都是不可见的。

static关键字

它是C,C++中都存在的关键字,它主要有三种使用方式,其中前两种只指在C语言中使用,第三种在C++中使用。

(1)局部静态变量

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

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

下面就这三种使用方式及区别

一、局部静态变量

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

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

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

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

二、外部静态变量/函数

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

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

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

注意:

不能将union成员声明为static的,然而,对于全局的匿名union,必须显式的声明为static。

register关键字

只有函数参数和局部变量可被声明为register。意思是,在可能的情况下,该变量被存储在CPU寄存器中。register变量和auto变量一样,它的生命周期只维持在它所声明的块中。编译器并不赞成程序员指定register变量。实际的情况是,编译器会根据全局优化的需要自动决定是否采用register类型。

extern关键字

extern用在声明语句中表示该对象或变量是在其它编译单元中(不能说是其它文件,因为有些文件,如头文件不是编译单元)定义的;如果用在定义语句中,表示该变量对外部可见。

注意extern与#include作用的区别:

例1,使用extern:

//out.h

int a = 10;

//out.cpp

#include "out.h"

//example.cpp

#include <iostream>

using namespace std;

extern int a;

int _tmain(int argc, _TCHAR* argv[])

{

cout<<"a="<<a<<endl;

system("pause");

return 0;

}

编译链接流程:

由于out.cpp文件引用了out.h文件,所以out.cpp文件的内容变成了int a =10;,编译时生成编译单元out.obj(out.o),其中定义了变量a。example.cpp文件中出现了对a的引用cout<<"a="<<a<<endl;,但该文件中没有a的定义(extern inta;只是一个声明),而且包含的头文件中也没有,但是由于有声明extern inta;,表明a是在其它编译单元中定义的,编译不出错。最后链接器在编译单元out.obj(out.o)中找到a的定义,建立连接关系,生成最后的exe文件。该工程中有两个编译单元,最后链接成一个exe文件。

例2,使用#include:

//out.h

int a = 20;

//example.cpp

#include "out.h"

#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])

{

cout<<"a="<<a<<endl;

system("pause");

return 0;

}

编译链接流程:

example.cpp文件中出现了对a的引用cout<<"a="<<a<<endl;,但该文件中没有a的定义,但是包含的头文件out.h中有,这样在编译之前,头文件out.h展开到example.cpp文件中,相当于example.cpp文件中定义了a(int a = 20;),编译成功。最后链接器链接编译单元生成最后的exe文件。该工程中只有一个编译单元,最后链接成一个exe文件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: