返回顶部
首页 > 资讯 > 精选 >怎么区分作用域,存储器,链接属性
  • 186
分享到

怎么区分作用域,存储器,链接属性

2023-06-15 23:06:23 186人浏览 泡泡鱼
摘要

本篇内容介绍了“怎么区分作用域,存储器,链接属性”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!作用域C语言中,作用域用来描述标识符能够被哪些

本篇内容介绍了“怎么区分作用域,存储器,链接属性”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

作用域

C语言中,作用域用来描述标识符能够被哪些区域访问。

而常见作用域有以下几种:

  • 块作用域,可见范围是从定义处到包含该定义的块结尾

  • 函数作用域,Goto语句的标签就具有函数作用域

  • 文件作用域,从定义处到定义该文件的末尾都可见。定义在函数之外的变量,就具有文件作用域了。

  • 函数原型作用域,从形参定义处到原型声明结束

为了便于说明,我们来看一个例子,就很容易理解了:

 #include <stdio.h> int num1 = 222;         //定位在函数外,具有文件作用域 static int num2 = 111;  //定义在函数外,具有文件作用域 int swap(int *a,int *b); //这里的a,b是函数原型作用域 int swap(int *a,int *b) {     if(NULL== a || NULL == b)         goto error;         else     {         int temp = *a;  //定义在函数内,块作用域         *a = *b;         *b = temp;         return 0;     }     //printf("temp is %d\n",temp);   //因为temp具有块作用域,因此在这里不能直接使用     error://goto语句的标签,函数作用域,因此在前面就可以引用         {             printf("input para is NULL\n");             return -1;         } } int main(void) {     printf("num1=%d,num2=%d\n",num1,num2);     swap(&num1,&num2);  //num1 num2具有文件作用域,可以在main函数中直接使用     printf("num1=%d,num2=%d",num1,num2);     return 0; }

可以看到,error标签具有函数作用域,整个函数内都可见,而temp具有块作用域,因此在大括号外部,不能直接使用它。而num1和num2具有文件作用域,因此main函数可以直接使用它。

链接属性

在《hello程序是如何变成可执行文件的》我们说到了编译的过程,最后一个步骤就是链接。链接属性决定了在不同作用域的同名标识符能否绑定到同一个对象或者函数。或者说,不同作用域的标识符在编译后是否是同一个实体。

c变量有三种链接属性:

  • 外部链接,extern修饰的,或者没有static修饰的具有文件作用域的变量具有外部链接属性

  • 内部链接,static修饰的具有文件作用域的变量具有内部链接属性

  • 无链接,块作用域,函数作用域和函数原型作用域的变量无链接属性

再稍作解释,没有static修饰,且具有文件作用域的变量,他们在链接时,多个同名标识符的变量最终都绑定到同一个实体。而static修饰的具有文件作用域的变量就不一样了,不同文件内,即便标识符名字相同,它们也绑定到了不同的实体。

因此,如果我们希望某个变量或函数只在某一个文件使用,那么使用static修饰是一个很好的做法。

同样的,来看一个例子。

 #include <stdio.h> int a = 5;   //文件作用域,外部链接属性,其他文件可通过extern int a的方式使用该文件的a static b = 6;  //文件作用域,内部链接属性,即便其他文件也有同名标识符,它们也是不同的 int main(void) {     int sum = 0 ; //无链接属性     sum = a + b;     printf("sum is %d\n",sum);     return 0; }

从代码中可以看到,a和b都具有文件作用域,a具有外部链接属性,而b具有内部链接属性,sum具有块作用域,因此无链接属性。

存储期

实际上作用域和链接属性都描述了标识符的可见性,而存储期则描述了这些标识符对应的对象的生存期。存储期,也分下面几种:

  • 静态存储期,程序执行期间一直都在,文件作用域的变量具有静态存储期

  • 自动存储期,它(变长数组除外)从块开始,到块末尾,因此,块作用域的变量具有自动存储期,它在栈中存储,需要显式初始化。

  • 动态分配存储期,即通过malloc分配内存的变量。它在堆中存储,需要显式初始。

  • 线程存储期,从名字可以知道, 它与线程相关,使用关键字_Thread_local声明的变量具有线程存储期,它从声明到线程结束一直存在。

  • 关于初始化,可参考《C语言入坑指南-被遗忘的初始化》。

同样地,我们通过下面的代码来更好地理解存储期

 #include <stdio.h> int num1 = 222;         //静态存储期 static int num2 = 111;  //静态存储期 int add(int a,int b) {     static int tempSum = 0;  //静态存储期     tempSum = tempSum + a + b;     return tempSum; } int main(void) {     printf("num1=%d,num2=%d\n",num1,num2);     int sum = 0;  //自动存储期     sum = add(num1,num2);     printf("first time sum=%d\n",sum);//sum = 333     sum = add(num1,num2);     printf("second time sum=%d\n",sum); //sum = 666     return 0; }

另外,如果我们通过nm命令查看编译出来的程序文件的符号表,我们可以找到num1,num2,tempSum,而没有sum,前者所用的内存数量在编译时就确定了。

GCc -g -o lifetime lifetime.c  $ nm lifetime|grep num1 0000000000601038 D num1 $ nm lifetime|grep num2 000000000060103c d num2 $ nm lifetime|grep tempSum 0000000000601044 b tempSum.2289 $ nm lifetime|grep sum $

什么全局变量,局部变量,静态局部变量,静态全局变量

到这里,我们就可以很容易区分上面的变量类型了。实际上这里只是换了一种说法:

全局:具有文件作用域的变量

静态:具有静态存储期或内部链接属性

局部:具有函数或块作用域的变量

因而结合起来,也就很好理解了。

  • 局部变量:函数或块作用域的变量

  • 静态局部变量:函数或块作用域,静态存储期

  • 全局变量:具有文件作用域的变量

  • 静态全局变量:内部链接属性的,具有文件作用域的变量

当然,这仅仅是为了区分它们,这并不是它们的严格定义。更好的方法,是通过代码来理解:

#include <stdio.h> int num1 = 222;         //全局变量 static int num2 = 111;  //静态全局变量 int add(int a,int b) {     static int tempSum = 0;  //静态局部变量     tempSum = tempSum + a + b;     return tempSum; } int main(void) {     printf("num1=%d,num2=%d\n",num1,num2);     int sum = 0;  //局部变量     sum = add(num1,num2);     printf("first time sum=%d\n",sum);//sum = 333     return 0; }

“怎么区分作用域,存储器,链接属性”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 怎么区分作用域,存储器,链接属性

本文链接: https://lsjlt.com/news/281846.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 怎么区分作用域,存储器,链接属性
    本篇内容介绍了“怎么区分作用域,存储器,链接属性”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!作用域C语言中,作用域用来描述标识符能够被哪些...
    99+
    2023-06-15
  • C语言链接属性怎么应用
    小编给大家分享一下C语言链接属性怎么应用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!什么是链接属性链接属性与C语言中各个目标文件及函数的链接过程有关,用于认定不...
    99+
    2023-06-29
  • 怎么在python中使用__dict__存储属性
    怎么在python中使用__dict__存储属性?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Python的优点有哪些1、简单易用,与C/C++、Java、C#...
    99+
    2023-06-14
  • C语言中的变量作用域、链接和存储期的意义是什么
    小编给大家分享一下C语言中的变量作用域、链接和存储期的意义是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在c中变量有三种性质:1、存储期限:变量的存储期限决...
    99+
    2023-06-15
  • CSS中clip-path区域裁剪属性怎么用
    这篇文章主要为大家展示了“CSS中clip-path区域裁剪属性怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“CSS中clip-path区域裁剪属性怎么用...
    99+
    2024-04-02
  • 怎么掌握js作用域链、内存回收、变量、闭包
    本篇内容介绍了“怎么掌握js作用域链、内存回收、变量、闭包”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一...
    99+
    2024-04-02
  • html怎么用超链接打开新窗口时控制其属性
    这篇文章主要讲解了“html怎么用超链接打开新窗口时控制其属性”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“html怎么用超链接打开新窗口时控制其属性”吧!...
    99+
    2024-04-02
  • 云服务器怎么分区域使用
    地域划分的优势 云服务器可以按照地域划分使用,这有以下几个优势。首先,云服务器可以根据不同的区域提供不同的服务,这可以提高服务的灵活性和可靠性。例如,在欧洲或亚洲地区,云服务器可以提供更高效的数据处理和存储服务,而在非洲或拉丁美洲地区...
    99+
    2023-10-28
    区域 服务器
  • C++变量存储的生命周期与作用域怎么应用
    这篇文章主要介绍“C++变量存储的生命周期与作用域怎么应用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++变量存储的生命周期与作用域怎么应用”文章能帮助大家解决问题。auto类型:非静态的局部变...
    99+
    2023-07-04
  • Cassandra怎么实现高可用性和分布式存储
    Cassandra是一个分布式NoSQL数据库系统,它可以实现高可用性和分布式存储的两种方法: 复制:Cassandra使用复制...
    99+
    2024-04-09
    Cassandra
  • 怎么使用CSS属性选择器来拼接HTML的DNA
    这篇文章主要介绍了怎么使用CSS属性选择器来拼接HTML的DNA,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。CSS属性选择器非常神奇,它们可以帮你避免添加数不胜数的类名,从...
    99+
    2023-06-08
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作