auto、register、static、extern等存储类修饰符的区别
创始人
2024-07-29 02:10:38
0次

存储类型修饰符可以修改标识符的链接和对应对象的生存周期;标识符有链接,而非生命周期;对象有生存周期,而非链接;函数标识符只可用static、extern修饰,函数参数只可用register修饰。

一、标识符的链接(linkage)

(1)外部链接

表示在整个程序中(多个程序文件)是相同的函数或对象。常见的有,在函数体外声明的extern变量。

(2)内部链接

表示只在当前程序文件中是相同的函数或对象。其它程序文件不能对其进行访问。常见的有,在函数体外声明的static变量。

(3)无链接

一般声明在函数内部的auto、register变量、还有函数的参数,都是无链接。它的作用域是函数内部。

二、对象的生存周期(lifetime)

(1)静态生存周期

具有静态生存周期的所有对象,都是在程序开始执行之前就被事先创建和初始化。它们的寿命覆盖整个程序的执行过程。如在函数内定义了一个static变量,那第一次调用该函数后,该变量的值将会被保留,当第二次被调用时,该变量的值还是第一次调用结束时的值。

(2)自动生存周期

自动生存周期的对象的寿命由“对象定义所处在的大括号{}”决定。每次程序执行流进入一个语句块,此语句块自动生存周期的对象就会被创建一个新实例,同时被初始化。

三、存储类修饰符

(1)auto

auto修饰符只能用在函数内的对象声明。声明中有auto修饰符的对象具有自动生存周期。

在ANSI C中,函数内的对象声明在默认情况下有自动生存周期,所以在函数内声明时auto可省略。

(2)register

当声明对象有自动生存周期时,可以使用register修饰符。因此,register也只能用在函数内的声明中。
此关键字告诉编译器:此对象的存取应该尽量快,最好存储在CPU的寄存器中。然而,编译器不见得会这么做。
另外要注意的是,当一个对象声明为register,就不可使用地址运算符&了,因为它有可能被放到寄存器中。

(3)static

函数标识符如果被声明为static,就具有静态生命周期。如果是定义在函数外,那么该对象具有内部链接,其它程序文件不能对其访问。如果是定义在函数内,那么该对象具有无链接,函数外不能对其访问。

注意:static变量初始化时,只能用常量。

(4)extern

如果声明在函数外,那么该对象具有外部链接,能够在其它程序文件使用。但要注意它有可能会被函数内定义的重名的变量所隐藏起来。

如果声明在函数内,该对象具有何种链接取决于当前程序文件中定义在函数外的相同名字的对象。如果在函数外也定义了一下相同名字的static对象,则该函数内的对象具有无链接,否则具有外部链接。

extern的对象都具有静态生命周期。

使用extern时,注意不能重复定义,否则编译报错,如:

程序文件一:

  1. extern int a = 10; //编译警告,extern的变量最好不要初始化 

 

程序文件二:

  1. extern int a = 20; //重复定义,应改为extern int a; 

 

一般最好这样,如果需要初始化,可把extern修饰符去掉(但也不要重复定义),另外如果其它程序文件也需要用到该变量,可用extern来声明该变量。这样会比较清晰。

(5)缺省修饰符

函数内,与auto相同;函数外,与extern相同。


 

例子:
 

  1. int func1(void); //func1具有外部链接;    
  2. int a = 10; //a具有外部链接,静态生存周期;    
  3. extern int b = 1; //b具有外部链接,静态生存周期。但编译会有警告extern变量不应初始化,同时也要注意是否会重复定义;    
  4. static int c; //c具有内部链接,静态生存周期;    
  5. static int e; //e具有内部链接,静态生存周期;    
  6. static void func2(int d){ //func2具有内部链接;参数d具有无链接,自动生存周期;    
  7. extern int a; //a与上面的a一样(同一变量),具有外部链接,静态生存周期。注意这里的不会被默认初始为0,它只是个声明;    
  8. int b = 2; //b具有无链接,自动生存同期。并且将上面声明的b隐藏起来;    
  9. extern int c; //c与上面的c一样,维持内部链接,静态生存周期。注意这里的不会被默认初始为0,它只是个声明;    
  10. //如果去掉了extern修饰符,就跟b类似了,无链接,自动生存周期,把上面声明的c隐藏起来;    
  11. static int e; //e具有无链接,静态生存周期。并且将上面声明的e隐藏起来;初始化值为0;    
  12. static int f; //f具有无链接,静态生存周期;    
  13. }  

【编辑推荐】

  1. 浅谈C/C++中的顺序点和副作用
  2. C++连接mysql数据库的两种方法
  3. C++中的指针用法汇集
  4. C++ Virtual详解

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
30分钟搞定iOS自定义相机 最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...